001: /*
002: * Written by Doug Lea with assistance from members of JCP JSR-166
003: * Expert Group and released to the public domain, as explained at
004: * http://creativecommons.org/licenses/publicdomain
005: */
006:
007: package java.util.concurrent.locks;
008:
009: import java.util.*;
010: import java.util.concurrent.*;
011: import java.util.concurrent.atomic.*;
012:
013: /**
014: * A reentrant mutual exclusion {@link Lock} with the same basic
015: * behavior and semantics as the implicit monitor lock accessed using
016: * <tt>synchronized</tt> methods and statements, but with extended
017: * capabilities.
018: *
019: * <p> A <tt>ReentrantLock</tt> is <em>owned</em> by the thread last
020: * successfully locking, but not yet unlocking it. A thread invoking
021: * <tt>lock</tt> will return, successfully acquiring the lock, when
022: * the lock is not owned by another thread. The method will return
023: * immediately if the current thread already owns the lock. This can
024: * be checked using methods {@link #isHeldByCurrentThread}, and {@link
025: * #getHoldCount}.
026: *
027: * <p> The constructor for this class accepts an optional
028: * <em>fairness</em> parameter. When set <tt>true</tt>, under
029: * contention, locks favor granting access to the longest-waiting
030: * thread. Otherwise this lock does not guarantee any particular
031: * access order. Programs using fair locks accessed by many threads
032: * may display lower overall throughput (i.e., are slower; often much
033: * slower) than those using the default setting, but have smaller
034: * variances in times to obtain locks and guarantee lack of
035: * starvation. Note however, that fairness of locks does not guarantee
036: * fairness of thread scheduling. Thus, one of many threads using a
037: * fair lock may obtain it multiple times in succession while other
038: * active threads are not progressing and not currently holding the
039: * lock.
040: *
041: * <p> It is recommended practice to <em>always</em> immediately
042: * follow a call to <tt>lock</tt> with a <tt>try</tt> block, most
043: * typically in a before/after construction such as:
044: *
045: * <pre>
046: * class X {
047: * private final ReentrantLock lock = new ReentrantLock();
048: * // ...
049: *
050: * public void m() {
051: * lock.lock(); // block until condition holds
052: * try {
053: * // ... method body
054: * } finally {
055: * lock.unlock()
056: * }
057: * }
058: * }
059: * </pre>
060: *
061: * <p>In addition to implementing the {@link Lock} interface, this
062: * class defines methods <tt>isLocked</tt> and
063: * <tt>getLockQueueLength</tt>, as well as some associated
064: * <tt>protected</tt> access methods that may be useful for
065: * instrumentation and monitoring.
066: *
067: * <p> Serialization of this class behaves in the same way as built-in
068: * locks: a deserialized lock is in the unlocked state, regardless of
069: * its state when serialized.
070: *
071: * <p> This lock supports a maximum of 2147483648 recursive locks by
072: * the same thread.
073: *
074: * @since 1.5
075: * @author Doug Lea
076: *
077: */
078: public class ReentrantLock implements Lock, java.io.Serializable {
079: private static final long serialVersionUID = 7373984872572414699L;
080: /** Synchronizer providing all implementation mechanics */
081: private final Sync sync;
082:
083: /**
084: * Base of synchronization control for this lock. Subclassed
085: * into fair and nonfair versions below. Uses AQS state to
086: * represent the number of holds on the lock.
087: */
088: static abstract class Sync extends AbstractQueuedSynchronizer {
089: /** Current owner thread */
090: transient Thread owner;
091:
092: /**
093: * Perform {@link Lock#lock}. The main reason for subclassing
094: * is to allow fast path for nonfair version.
095: */
096: abstract void lock();
097:
098: /**
099: * Perform non-fair tryLock. tryAcquire is
100: * implemented in subclasses, but both need nonfair
101: * try for trylock method
102: */
103: final boolean nonfairTryAcquire(int acquires) {
104: final Thread current = Thread.currentThread();
105: int c = getState();
106: if (c == 0) {
107: if (compareAndSetState(0, acquires)) {
108: owner = current;
109: return true;
110: }
111: } else if (current == owner) {
112: setState(c + acquires);
113: return true;
114: }
115: return false;
116: }
117:
118: protected final boolean tryRelease(int releases) {
119: int c = getState() - releases;
120: if (Thread.currentThread() != owner)
121: throw new IllegalMonitorStateException();
122: boolean free = false;
123: if (c == 0) {
124: free = true;
125: owner = null;
126: }
127: setState(c);
128: return free;
129: }
130:
131: protected final boolean isHeldExclusively() {
132: return getState() != 0 && owner == Thread.currentThread();
133: }
134:
135: final ConditionObject newCondition() {
136: return new ConditionObject();
137: }
138:
139: // Methods relayed from outer class
140:
141: final Thread getOwner() {
142: int c = getState();
143: Thread o = owner;
144: return (c == 0) ? null : o;
145: }
146:
147: final int getHoldCount() {
148: int c = getState();
149: Thread o = owner;
150: return (o == Thread.currentThread()) ? c : 0;
151: }
152:
153: final boolean isLocked() {
154: return getState() != 0;
155: }
156:
157: /**
158: * Reconstitute this lock instance from a stream
159: * @param s the stream
160: */
161: private void readObject(java.io.ObjectInputStream s)
162: throws java.io.IOException, ClassNotFoundException {
163: s.defaultReadObject();
164: setState(0); // reset to unlocked state
165: }
166: }
167:
168: /**
169: * Sync object for non-fair locks
170: */
171: final static class NonfairSync extends Sync {
172: /**
173: * Perform lock. Try immediate barge, backing up to normal
174: * acquire on failure.
175: */
176: final void lock() {
177: if (compareAndSetState(0, 1))
178: owner = Thread.currentThread();
179: else
180: acquire(1);
181: }
182:
183: protected final boolean tryAcquire(int acquires) {
184: return nonfairTryAcquire(acquires);
185: }
186: }
187:
188: /**
189: * Sync object for fair locks
190: */
191: final static class FairSync extends Sync {
192: final void lock() {
193: acquire(1);
194: }
195:
196: /**
197: * Fair version of tryAcquire. Don't grant access unless
198: * recursive call or no waiters or is first.
199: */
200: protected final boolean tryAcquire(int acquires) {
201: final Thread current = Thread.currentThread();
202: int c = getState();
203: if (c == 0) {
204: Thread first = getFirstQueuedThread();
205: if ((first == null || first == current)
206: && compareAndSetState(0, acquires)) {
207: owner = current;
208: return true;
209: }
210: } else if (current == owner) {
211: setState(c + acquires);
212: return true;
213: }
214: return false;
215: }
216: }
217:
218: /**
219: * Creates an instance of <tt>ReentrantLock</tt>.
220: * This is equivalent to using <tt>ReentrantLock(false)</tt>.
221: */
222: public ReentrantLock() {
223: sync = new NonfairSync();
224: }
225:
226: /**
227: * Creates an instance of <tt>ReentrantLock</tt> with the
228: * given fairness policy.
229: * @param fair true if this lock will be fair; else false
230: */
231: public ReentrantLock(boolean fair) {
232: sync = (fair) ? new FairSync() : new NonfairSync();
233: }
234:
235: /**
236: * Acquires the lock.
237: *
238: * <p>Acquires the lock if it is not held by another thread and returns
239: * immediately, setting the lock hold count to one.
240: *
241: * <p>If the current thread
242: * already holds the lock then the hold count is incremented by one and
243: * the method returns immediately.
244: *
245: * <p>If the lock is held by another thread then the
246: * current thread becomes disabled for thread scheduling
247: * purposes and lies dormant until the lock has been acquired,
248: * at which time the lock hold count is set to one.
249: */
250: public void lock() {
251: sync.lock();
252: }
253:
254: /**
255: * Acquires the lock unless the current thread is
256: * {@link Thread#interrupt interrupted}.
257: *
258: * <p>Acquires the lock if it is not held by another thread and returns
259: * immediately, setting the lock hold count to one.
260: *
261: * <p>If the current thread already holds this lock then the hold count
262: * is incremented by one and the method returns immediately.
263: *
264: * <p>If the lock is held by another thread then the
265: * current thread becomes disabled for thread scheduling
266: * purposes and lies dormant until one of two things happens:
267: *
268: * <ul>
269: *
270: * <li>The lock is acquired by the current thread; or
271: *
272: * <li>Some other thread {@link Thread#interrupt interrupts} the current
273: * thread.
274: *
275: * </ul>
276: *
277: * <p>If the lock is acquired by the current thread then the lock hold
278: * count is set to one.
279: *
280: * <p>If the current thread:
281: *
282: * <ul>
283: *
284: * <li>has its interrupted status set on entry to this method; or
285: *
286: * <li>is {@link Thread#interrupt interrupted} while acquiring
287: * the lock,
288: *
289: * </ul>
290: *
291: * then {@link InterruptedException} is thrown and the current thread's
292: * interrupted status is cleared.
293: *
294: * <p>In this implementation, as this method is an explicit interruption
295: * point, preference is
296: * given to responding to the interrupt over normal or reentrant
297: * acquisition of the lock.
298: *
299: * @throws InterruptedException if the current thread is interrupted
300: */
301: public void lockInterruptibly() throws InterruptedException {
302: sync.acquireInterruptibly(1);
303: }
304:
305: /**
306: * Acquires the lock only if it is not held by another thread at the time
307: * of invocation.
308: *
309: * <p>Acquires the lock if it is not held by another thread and
310: * returns immediately with the value <tt>true</tt>, setting the
311: * lock hold count to one. Even when this lock has been set to use a
312: * fair ordering policy, a call to <tt>tryLock()</tt> <em>will</em>
313: * immediately acquire the lock if it is available, whether or not
314: * other threads are currently waiting for the lock.
315: * This "barging" behavior can be useful in certain
316: * circumstances, even though it breaks fairness. If you want to honor
317: * the fairness setting for this lock, then use
318: * {@link #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
319: * which is almost equivalent (it also detects interruption).
320: *
321: * <p> If the current thread
322: * already holds this lock then the hold count is incremented by one and
323: * the method returns <tt>true</tt>.
324: *
325: * <p>If the lock is held by another thread then this method will return
326: * immediately with the value <tt>false</tt>.
327: *
328: * @return <tt>true</tt> if the lock was free and was acquired by the
329: * current thread, or the lock was already held by the current thread; and
330: * <tt>false</tt> otherwise.
331: */
332: public boolean tryLock() {
333: return sync.nonfairTryAcquire(1);
334: }
335:
336: /**
337: * Acquires the lock if it is not held by another thread within the given
338: * waiting time and the current thread has not been
339: * {@link Thread#interrupt interrupted}.
340: *
341: * <p>Acquires the lock if it is not held by another thread and returns
342: * immediately with the value <tt>true</tt>, setting the lock hold count
343: * to one. If this lock has been set to use a fair ordering policy then
344: * an available lock <em>will not</em> be acquired if any other threads
345: * are waiting for the lock. This is in contrast to the {@link #tryLock()}
346: * method. If you want a timed <tt>tryLock</tt> that does permit barging on
347: * a fair lock then combine the timed and un-timed forms together:
348: *
349: * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
350: * </pre>
351: *
352: * <p>If the current thread
353: * already holds this lock then the hold count is incremented by one and
354: * the method returns <tt>true</tt>.
355: *
356: * <p>If the lock is held by another thread then the
357: * current thread becomes disabled for thread scheduling
358: * purposes and lies dormant until one of three things happens:
359: *
360: * <ul>
361: *
362: * <li>The lock is acquired by the current thread; or
363: *
364: * <li>Some other thread {@link Thread#interrupt interrupts} the current
365: * thread; or
366: *
367: * <li>The specified waiting time elapses
368: *
369: * </ul>
370: *
371: * <p>If the lock is acquired then the value <tt>true</tt> is returned and
372: * the lock hold count is set to one.
373: *
374: * <p>If the current thread:
375: *
376: * <ul>
377: *
378: * <li>has its interrupted status set on entry to this method; or
379: *
380: * <li>is {@link Thread#interrupt interrupted} while acquiring
381: * the lock,
382: *
383: * </ul>
384: * then {@link InterruptedException} is thrown and the current thread's
385: * interrupted status is cleared.
386: *
387: * <p>If the specified waiting time elapses then the value <tt>false</tt>
388: * is returned.
389: * If the time is
390: * less than or equal to zero, the method will not wait at all.
391: *
392: * <p>In this implementation, as this method is an explicit interruption
393: * point, preference is
394: * given to responding to the interrupt over normal or reentrant
395: * acquisition of the lock, and over reporting the elapse of the waiting
396: * time.
397: *
398: * @param timeout the time to wait for the lock
399: * @param unit the time unit of the timeout argument
400: *
401: * @return <tt>true</tt> if the lock was free and was acquired by the
402: * current thread, or the lock was already held by the current thread; and
403: * <tt>false</tt> if the waiting time elapsed before the lock could be
404: * acquired.
405: *
406: * @throws InterruptedException if the current thread is interrupted
407: * @throws NullPointerException if unit is null
408: *
409: */
410: public boolean tryLock(long timeout, TimeUnit unit)
411: throws InterruptedException {
412: return sync.tryAcquireNanos(1, unit.toNanos(timeout));
413: }
414:
415: /**
416: * Attempts to release this lock.
417: *
418: * <p>If the current thread is the
419: * holder of this lock then the hold count is decremented. If the
420: * hold count is now zero then the lock is released. If the
421: * current thread is not the holder of this lock then {@link
422: * IllegalMonitorStateException} is thrown.
423: * @throws IllegalMonitorStateException if the current thread does not
424: * hold this lock.
425: */
426: public void unlock() {
427: sync.release(1);
428: }
429:
430: /**
431: * Returns a {@link Condition} instance for use with this
432: * {@link Lock} instance.
433: *
434: * <p>The returned {@link Condition} instance supports the same
435: * usages as do the {@link Object} monitor methods ({@link
436: * Object#wait() wait}, {@link Object#notify notify}, and {@link
437: * Object#notifyAll notifyAll}) when used with the built-in
438: * monitor lock.
439: *
440: * <ul>
441: *
442: * <li>If this lock is not held when any of the {@link Condition}
443: * {@link Condition#await() waiting} or {@link Condition#signal
444: * signalling} methods are called, then an {@link
445: * IllegalMonitorStateException} is thrown.
446: *
447: * <li>When the condition {@link Condition#await() waiting}
448: * methods are called the lock is released and, before they
449: * return, the lock is reacquired and the lock hold count restored
450: * to what it was when the method was called.
451: *
452: * <li>If a thread is {@link Thread#interrupt interrupted} while
453: * waiting then the wait will terminate, an {@link
454: * InterruptedException} will be thrown, and the thread's
455: * interrupted status will be cleared.
456: *
457: * <li> Waiting threads are signalled in FIFO order
458: *
459: * <li>The ordering of lock reacquisition for threads returning
460: * from waiting methods is the same as for threads initially
461: * acquiring the lock, which is in the default case not specified,
462: * but for <em>fair</em> locks favors those threads that have been
463: * waiting the longest.
464: *
465: * </ul>
466: *
467: * @return the Condition object
468: */
469: public Condition newCondition() {
470: return sync.newCondition();
471: }
472:
473: /**
474: * Queries the number of holds on this lock by the current thread.
475: *
476: * <p>A thread has a hold on a lock for each lock action that is not
477: * matched by an unlock action.
478: *
479: * <p>The hold count information is typically only used for testing and
480: * debugging purposes. For example, if a certain section of code should
481: * not be entered with the lock already held then we can assert that
482: * fact:
483: *
484: * <pre>
485: * class X {
486: * ReentrantLock lock = new ReentrantLock();
487: * // ...
488: * public void m() {
489: * assert lock.getHoldCount() == 0;
490: * lock.lock();
491: * try {
492: * // ... method body
493: * } finally {
494: * lock.unlock();
495: * }
496: * }
497: * }
498: * </pre>
499: *
500: * @return the number of holds on this lock by the current thread,
501: * or zero if this lock is not held by the current thread.
502: */
503: public int getHoldCount() {
504: return sync.getHoldCount();
505: }
506:
507: /**
508: * Queries if this lock is held by the current thread.
509: *
510: * <p>Analogous to the {@link Thread#holdsLock} method for built-in
511: * monitor locks, this method is typically used for debugging and
512: * testing. For example, a method that should only be called while
513: * a lock is held can assert that this is the case:
514: *
515: * <pre>
516: * class X {
517: * ReentrantLock lock = new ReentrantLock();
518: * // ...
519: *
520: * public void m() {
521: * assert lock.isHeldByCurrentThread();
522: * // ... method body
523: * }
524: * }
525: * </pre>
526: *
527: * <p>It can also be used to ensure that a reentrant lock is used
528: * in a non-reentrant manner, for example:
529: *
530: * <pre>
531: * class X {
532: * ReentrantLock lock = new ReentrantLock();
533: * // ...
534: *
535: * public void m() {
536: * assert !lock.isHeldByCurrentThread();
537: * lock.lock();
538: * try {
539: * // ... method body
540: * } finally {
541: * lock.unlock();
542: * }
543: * }
544: * }
545: * </pre>
546: * @return <tt>true</tt> if current thread holds this lock and
547: * <tt>false</tt> otherwise.
548: */
549: public boolean isHeldByCurrentThread() {
550: return sync.isHeldExclusively();
551: }
552:
553: /**
554: * Queries if this lock is held by any thread. This method is
555: * designed for use in monitoring of the system state,
556: * not for synchronization control.
557: * @return <tt>true</tt> if any thread holds this lock and
558: * <tt>false</tt> otherwise.
559: */
560: public boolean isLocked() {
561: return sync.isLocked();
562: }
563:
564: /**
565: * Returns true if this lock has fairness set true.
566: * @return true if this lock has fairness set true.
567: */
568: public final boolean isFair() {
569: return sync instanceof FairSync;
570: }
571:
572: /**
573: * Returns the thread that currently owns the exclusive lock, or
574: * <tt>null</tt> if not owned. Note that the owner may be
575: * momentarily <tt>null</tt> even if there are threads trying to
576: * acquire the lock but have not yet done so. This method is
577: * designed to facilitate construction of subclasses that provide
578: * more extensive lock monitoring facilities.
579: * @return the owner, or <tt>null</tt> if not owned.
580: */
581: protected Thread getOwner() {
582: return sync.getOwner();
583: }
584:
585: /**
586: * Queries whether any threads are waiting to acquire. Note that
587: * because cancellations may occur at any time, a <tt>true</tt>
588: * return does not guarantee that any other thread will ever
589: * acquire. This method is designed primarily for use in
590: * monitoring of the system state.
591: *
592: * @return true if there may be other threads waiting to acquire
593: * the lock.
594: */
595: public final boolean hasQueuedThreads() {
596: return sync.hasQueuedThreads();
597: }
598:
599: /**
600: * Queries whether the given thread is waiting to acquire this
601: * lock. Note that because cancellations may occur at any time, a
602: * <tt>true</tt> return does not guarantee that this thread
603: * will ever acquire. This method is designed primarily for use
604: * in monitoring of the system state.
605: *
606: * @param thread the thread
607: * @return true if the given thread is queued waiting for this lock.
608: * @throws NullPointerException if thread is null
609: */
610: public final boolean hasQueuedThread(Thread thread) {
611: return sync.isQueued(thread);
612: }
613:
614: /**
615: * Returns an estimate of the number of threads waiting to
616: * acquire. The value is only an estimate because the number of
617: * threads may change dynamically while this method traverses
618: * internal data structures. This method is designed for use in
619: * monitoring of the system state, not for synchronization
620: * control.
621: * @return the estimated number of threads waiting for this lock
622: */
623: public final int getQueueLength() {
624: return sync.getQueueLength();
625: }
626:
627: /**
628: * Returns a collection containing threads that may be waiting to
629: * acquire. Because the actual set of threads may change
630: * dynamically while constructing this result, the returned
631: * collection is only a best-effort estimate. The elements of the
632: * returned collection are in no particular order. This method is
633: * designed to facilitate construction of subclasses that provide
634: * more extensive monitoring facilities.
635: * @return the collection of threads
636: */
637: protected Collection<Thread> getQueuedThreads() {
638: return sync.getQueuedThreads();
639: }
640:
641: /**
642: * Queries whether any threads are waiting on the given condition
643: * associated with this lock. Note that because timeouts and
644: * interrupts may occur at any time, a <tt>true</tt> return does
645: * not guarantee that a future <tt>signal</tt> will awaken any
646: * threads. This method is designed primarily for use in
647: * monitoring of the system state.
648: * @param condition the condition
649: * @return <tt>true</tt> if there are any waiting threads.
650: * @throws IllegalMonitorStateException if this lock
651: * is not held
652: * @throws IllegalArgumentException if the given condition is
653: * not associated with this lock
654: * @throws NullPointerException if condition null
655: */
656: public boolean hasWaiters(Condition condition) {
657: if (condition == null)
658: throw new NullPointerException();
659: if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
660: throw new IllegalArgumentException("not owner");
661: return sync
662: .hasWaiters((AbstractQueuedSynchronizer.ConditionObject) condition);
663: }
664:
665: /**
666: * Returns an estimate of the number of threads waiting on the
667: * given condition associated with this lock. Note that because
668: * timeouts and interrupts may occur at any time, the estimate
669: * serves only as an upper bound on the actual number of waiters.
670: * This method is designed for use in monitoring of the system
671: * state, not for synchronization control.
672: * @param condition the condition
673: * @return the estimated number of waiting threads.
674: * @throws IllegalMonitorStateException if this lock
675: * is not held
676: * @throws IllegalArgumentException if the given condition is
677: * not associated with this lock
678: * @throws NullPointerException if condition null
679: */
680: public int getWaitQueueLength(Condition condition) {
681: if (condition == null)
682: throw new NullPointerException();
683: if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
684: throw new IllegalArgumentException("not owner");
685: return sync
686: .getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject) condition);
687: }
688:
689: /**
690: * Returns a collection containing those threads that may be
691: * waiting on the given condition associated with this lock.
692: * Because the actual set of threads may change dynamically while
693: * constructing this result, the returned collection is only a
694: * best-effort estimate. The elements of the returned collection
695: * are in no particular order. This method is designed to
696: * facilitate construction of subclasses that provide more
697: * extensive condition monitoring facilities.
698: * @param condition the condition
699: * @return the collection of threads
700: * @throws IllegalMonitorStateException if this lock
701: * is not held
702: * @throws IllegalArgumentException if the given condition is
703: * not associated with this lock
704: * @throws NullPointerException if condition null
705: */
706: protected Collection<Thread> getWaitingThreads(Condition condition) {
707: if (condition == null)
708: throw new NullPointerException();
709: if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
710: throw new IllegalArgumentException("not owner");
711: return sync
712: .getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject) condition);
713: }
714:
715: /**
716: * Returns a string identifying this lock, as well as its lock
717: * state. The state, in brackets, includes either the String
718: * "Unlocked" or the String "Locked by"
719: * followed by the {@link Thread#getName} of the owning thread.
720: * @return a string identifying this lock, as well as its lock state.
721: */
722: public String toString() {
723: Thread owner = sync.getOwner();
724: return super .toString()
725: + ((owner == null) ? "[Unlocked]"
726: : "[Locked by thread " + owner.getName() + "]");
727: }
728: }
|