ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/main/java/util/concurrent/ReentrantLock.java
Revision: 1.7
Committed: Sat Jun 7 17:10:36 2003 UTC (21 years ago) by dl
Branch: MAIN
CVS Tags: JSR166_PRELIMINARY_TEST_RELEASE_1
Changes since 1.6: +9 -12 lines
Log Message:
Made comments match code

File Contents

# Content
1 /*
2 * Written by Doug Lea with assistance from members of JCP JSR-166
3 * Expert Group and released to the public domain. Use, modify, and
4 * redistribute this code in any way without acknowledgement.
5 */
6
7 package java.util.concurrent;
8 import java.util.concurrent.atomic.*;
9 import java.util.Date;
10
11
12 /**
13 * A reentrant mutual exclusion lock.
14 * <p><tt>ReentrantLock</tt> defines a stand-alone {@link Lock} class with
15 * the same basic behavior and semantics as the implicit
16 * monitor lock accessed by the use of <tt>synchronized</tt> methods and
17 * statements, but without the forced block-structured locking and unlocking
18 * that occurs with <tt>synchronized</tt> methods and
19 * statements.
20 *
21 * <p>The order in which blocked threads are granted the lock is not
22 * specified.
23 *
24 * <p>If you want a non-reentrant mutual exclusion lock then it is a simple
25 * matter to use a reentrant lock in a non-reentrant way by ensuring that
26 * the lock is not held by the current thread prior to locking.
27 * See {@link #getHoldCount} for a way to check this.
28 *
29 *
30 * <p><tt>ReentrantLock</tt> instances are intended to be used primarily
31 * in before/after constructions such as:
32 *
33 * <pre>
34 * class X {
35 * ReentrantLock lock;
36 * // ...
37 *
38 * public void m() {
39 * lock.lock(); // block until condition holds
40 * try {
41 * // ... method body
42 * } finally {
43 * lock.unlock()
44 * }
45 * }
46 * }
47 * </pre>
48 *
49 * <p>This class supports the interruption of lock acquisition and provides a
50 * {@link #newCondition Condition} implementation that supports the
51 * interruption of thread suspension.
52 *
53 * <p>Except where noted, passing a <tt>null</tt> value for any parameter
54 * will result in a {@link NullPointerException} being thrown.
55 *
56 * @since 1.5
57 * @spec JSR-166
58 * @revised $Date: 2003/06/06 18:42:17 $
59 * @editor $Author: dl $
60 * @author Doug Lea
61 *
62 **/
63 public class ReentrantLock extends ReentrantLockQueueNode implements Lock, java.io.Serializable {
64 /*
65 This is a fastpath/slowpath algorithm.
66
67 * The basic algorithm looks like this, ignoring reentrance,
68 cancellation, timeouts, error checking etc:
69 Lock:
70 if (!fair && casOwner(null, currentThread)) // fastpath
71 return;
72 node = create and enq a wait node;
73 for (;;) {
74 if (node is first on queue) {
75 if (casOwner(null, currentThread)) {
76 deq(node);
77 return;
78 }
79 }
80 park(currentThread);
81 }
82
83 Unlock:
84 owner = null; // volatile assignment
85 h = first node on queue;
86 if (h != null) unpark(h's successor's thread);
87
88 * The fast path uses one atomic CAS operation, plus one
89 StoreLoad barrier (i.e., volatile-write-barrier) per
90 lock/unlock pair. The "owner" field is handled as a simple
91 spinlock. To lock, the owner field is set to current thread
92 using conditional atomic update. To unlock, the owner field
93 is set to null, checking if anyone needs waking up, if so
94 doing so. Recursive locks/unlocks instead increment/decrement
95 recursion field.
96
97 * By default, contended locks use a kind of "greedy" /
98 "renouncement" / barging / convoy-avoidance strategy: When a
99 lock is released, a waiting thread is signalled so that it can
100 (re)contend for the lock. It might lose and thus need to
101 rewait. This strategy has much higher throughput than
102 "directed handoff" because it reduces blocking of running
103 threads, but poorer fairness. The wait queue is FIFO, but
104 newly entering threads can barge ahead and grab lock before
105 woken waiters, so acquires are not strictly FIFO, and transfer
106 is not deterministically fair. It is probablistically fair
107 though. Earlier queued threads are allowed to recontend before
108 later queued threads, and each recontention has an unbiased
109 chance to succeed.
110
111 * The base class also sets up support for FairReentrantLock
112 subclass, that differs only in that barging is disabled when
113 there is contention, so locks proceed FIFO. There can be
114 some races in detecting contention, but it is still FIFO from
115 a definable (although complicated to describe) single point,
116 so qualifies as a FIFO lock.
117
118 * The wait queue is a variant of a "CLH" (Craig, Landin, and
119 Hagersten) lock. CLH locks are normally used for spinlocks.
120 We instead use them for blocking locks, but use the same basic
121 tactic of holding the information about whether a thread is
122 released (i.e, eligible to contend for ownership lock) in the
123 predecessor of each node. A node waits until its predecessor
124 says it is released. It is signalled when its predecessor
125 releases the lock. Each node of the queue otherwise serves as
126 a specific-notification-style monitor holding a single waiting
127 thread.
128
129 To enqueue into a CLH lock, you atomically splice it in as new
130 tail. To dequeue, you just set the head field.
131
132 +------+ prev +-----+ +-----+
133 head | | <---- | | <---- | | tail
134 +------+ +-----+ +-----+
135
136 The great thing about CLH Locks is that insertion into a CLH
137 queue requires only a single atomic operation on "tail", so
138 there is a simple atomic point of demarcation from unqueued to
139 queued. Similarly, dequeing involves only updating the
140 "head". However, it takes a bit more work for nodes to
141 determine who their successors are, in part to deal with
142 possible cancellation due to timeouts and interrupts.
143
144 The "prev" links (not used in original CLH locks), are mainly
145 needed to handle cancellation. If a node is cancelled, its
146 successor must be relinked to a non-cancelled predecessor. For
147 explanation in the case of spin locks, see the papers by Scott
148 & Scherer at
149 http://www.cs.rochester.edu/u/scott/synchronization/
150
151 Being first in the queue does not mean that you have the lock,
152 only that you may contend for it (by CAS'ing owner field). So
153 the currently released contender thread may need to rewait.
154
155 We also use "next" links to implement blocking mechanics. The
156 thread id for each node is kept in its node, so a predecessor
157 signals the next node to wake up by traversing next link to
158 determine which thread it is. Determination of successor must
159 avoid races with newly queued nodes to set the "next" fields
160 of their predecessors. This is solved by checking backwards
161 from the atomically updated "tail" when a node's successor
162 appears to be null.
163
164 Cancellation introduces some conservatism to the basic
165 algorithms. Since we must poll for cancellation of other
166 nodes, we can miss noticing whether a cancelled node is ahead
167 or behind us. This is dealt with by always unparking
168 successors upon cancellation, and not letting them park again
169 (by saturating release counts) until they stabilize on a new
170 predecessor.
171
172 * Threads waiting on Conditions use the same kind of nodes, but
173 only need to link them in simple (non-concurrent) linked
174 queues because they are only accessed when lock is held. To
175 wait, a thread makes a node inserted into a condition queue.
176 Upon signal, the node is transferred to the lock queue.
177 Special values of releaseStatus fields are used to mark which
178 queue a node is on.
179
180 * All suspension and resumption of threads uses the internal
181 JSR166 native park/unpark API. These are safe versions of
182 suspend/resume (plus timeout support) that avoid the intrinsic
183 race problems with suspend/resume: Park suspends if not
184 preceded by an unpark. Unpark resumes if waiting, else causes
185 next park not to suspend. While safe and efficient, these are
186 not general-purpose public operations because we cannot allow
187 code outside this package to randomly call these methods --
188 parks and unparks should be matched up. (It is OK to have more
189 unparks than unparks, but it causes threads to spuriously wake
190 up. So minimizing excessive unparks is a performance concern.)
191
192 * The ReentrantLock class extends package-private
193 ReentrantLockQueueNode class as an expedient and efficient
194 (although slightly sleazy) solution to serialization and
195 initialization problems -- we need head and tail nodes to be
196 initialized to a head node, so use the ReeantrantLock itself
197 as that node.
198 */
199
200 /*
201 Note that all fields are transient and defined in a way that
202 deserialized locks are in initial unlocked state.
203 */
204
205 /**
206 * Creates an instance of <tt>ReentrantLock</tt>.
207 */
208 public ReentrantLock() { }
209
210 /**
211 * Current owner of lock, or null iff the lock is free. Acquired
212 * only using CAS.
213 */
214 private transient volatile Thread owner;
215
216 /** Number of recursive acquires. Note: total holds = recursions+1 */
217 private transient int recursions;
218
219 /** Head of the wait queue, initialized to point to self as dummy node */
220 private transient volatile ReentrantLockQueueNode head = this;
221
222 /** Tail of the wait queue, initialized to point to self as dummy node */
223 private transient volatile ReentrantLockQueueNode tail = this;
224
225 // Atomics support
226
227 private final static AtomicReferenceFieldUpdater<ReentrantLock, Thread> ownerUpdater = new AtomicReferenceFieldUpdater<ReentrantLock, Thread>(new ReentrantLock[0], new Thread[0], "owner");
228 private final static AtomicReferenceFieldUpdater<ReentrantLock, ReentrantLockQueueNode> tailUpdater = new AtomicReferenceFieldUpdater<ReentrantLock, ReentrantLockQueueNode>(new ReentrantLock[0], new ReentrantLockQueueNode[0], "tail");
229 private final static AtomicReferenceFieldUpdater<ReentrantLock, ReentrantLockQueueNode> headUpdater = new AtomicReferenceFieldUpdater<ReentrantLock, ReentrantLockQueueNode>(new ReentrantLock[0], new ReentrantLockQueueNode[0], "head");
230 private final static AtomicIntegerFieldUpdater<ReentrantLockQueueNode> releaseStatusUpdater =
231 new AtomicIntegerFieldUpdater<ReentrantLockQueueNode>(new ReentrantLockQueueNode[0], "releaseStatus");
232
233 private boolean acquireOwner(Thread current) {
234 return ownerUpdater.compareAndSet(this, null, current);
235 }
236
237 private boolean casTail(ReentrantLockQueueNode cmp, ReentrantLockQueueNode val) {
238 return tailUpdater.compareAndSet(this, cmp, val);
239 }
240
241 private boolean casHead(ReentrantLockQueueNode cmp, ReentrantLockQueueNode val) {
242 return headUpdater.compareAndSet(this, cmp, val);
243 }
244
245 // casReleaseStatus non-private because also accessed by Conditions
246 final boolean casReleaseStatus(ReentrantLockQueueNode node, int cmp, int val) {
247 return releaseStatusUpdater.compareAndSet(node, cmp, val);
248 }
249
250 /**
251 * Special value for releaseStatus indicating that node is cancelled.
252 * Must be a large positive number.
253 */
254 static private final int CANCELLED = Integer.MAX_VALUE;
255
256 /**
257 * Special value for node releaseStatus indicating that node is on a
258 * condition queue. Must be large negative number.
259 */
260 static private final int ON_CONDITION_QUEUE = Integer.MIN_VALUE;
261
262 /**
263 * Special value for node releaseStatus indicating that node is in
264 * process of transfer. Must be negative and greater than
265 * ON_CONDITION_QUEUE.
266 */
267 static private final int TRANSFERRING = ON_CONDITION_QUEUE+1;
268
269
270 /**
271 * Utility to throw an exception if lock not held by given thread.
272 */
273 final void checkOwner(Thread current) {
274 if (current != owner)
275 throw new IllegalMonitorStateException();
276 }
277
278 /**
279 * Return whether lock wait queue is empty
280 */
281 final boolean queueEmpty() {
282 ReentrantLockQueueNode h = head; // force order of the volatile reads
283 return h == tail;
284 }
285
286 /**
287 * Insert node into queue. Return predecessor.
288 */
289 private ReentrantLockQueueNode enq(ReentrantLockQueueNode node) {
290 for (;;) {
291 ReentrantLockQueueNode p = tail;
292 node.prev = p; // prev must be valid before/upon CAS
293 if (casTail(p, node)) {
294 p.next = node; // Note: next field assignment lags CAS
295 return p;
296 }
297 }
298 }
299
300 /**
301 * Return true if it is OK to take fast path to lock.
302 * Overridden in FairReentrantLock.
303 */
304 boolean canBarge() {
305 return true;
306 }
307
308 /**
309 * Main locking code, parameterized across different policies.
310 * @param current current thread
311 * @param node its wait-node, if it already exists; else null in
312 * which case it is created,
313 * @param interruptible - true if can abort for interrupt or timeout
314 * @param nanos time to wait, or zero if untimed
315 * @return true if lock acquired (can be false only if interruptible)
316 */
317 final boolean doLock(Thread current,
318 ReentrantLockQueueNode node,
319 boolean interruptible,
320 long nanos) {
321 /*
322 * Bypass queueing if a recursive lock
323 */
324 if (owner == current) {
325 ++recursions;
326 return true;
327 }
328
329 long lastTime = 0; // for adjusting timeouts, below
330 boolean interrupted = false; // for restoring interrupt status on exit
331
332 /*
333 * p is our predecessor node, that holds releaseStatus giving
334 * permission to try to obtain lock if we are first in queue.
335 */
336 ReentrantLockQueueNode p;
337
338 /*
339 * Create and enqueue node if not already created. Nodes
340 * transferred from condition queues will already be created
341 * and queued.
342 */
343 if (node == null) {
344 node = new ReentrantLockQueueNode(current);
345 p = enq(node);
346 }
347 else
348 p = node.prev;
349
350 /*
351 * Repeatedly try to get ownership if first in queue, else
352 * block.
353 */
354 for (;;) {
355 /*
356 * If we are the first thread in queue, try to get the
357 * lock. (We must not try to get lock if we are not
358 * first.) Note that if we become first after p == head
359 * check, all is well -- we can be sure an unlocking
360 * thread will signal us.
361 */
362
363 if (p == head && acquireOwner(current)) {
364 if (interrupted) // re-interrupt on exit
365 current.interrupt();
366
367 p.next = null; // clear for GC and to suppress signals
368 node.thread = null;
369 node.prev = null;
370 head = node;
371 return true;
372 }
373
374 int releaseStatus = p.releaseStatus;
375
376 /*
377 * If our predecessor was cancelled, use its predecessor.
378 * There will always be a non-cancelled one somewhere
379 * because head node is never cancelled, so at worst we
380 * will hit it. (Note that because head is never
381 * cancelled, we can perform this check after trying to
382 * acquire ownership).
383 */
384 if (releaseStatus == CANCELLED) {
385 node.prev = p = p.prev;
386 }
387
388 /*
389 * Wait if we are not not first in queue, or if we are
390 * first, we have tried to acquire owner and failed since
391 * either entry or last release. (Note that releaseStatus can
392 * already be less than zero if we spuriously returned
393 * from a previous park or got new a predecessor due to
394 * cancellation.)
395 *
396 * We also don't wait if atomic decrement of releaseStatus
397 * fails. We just continue main loop on failure to
398 * atomically update releaseStatus because interference
399 * causing failure is almost surely due to someone
400 * releasing us anyway.
401 *
402 * Each wait consumes all available releases. Normally
403 * there is only one anyway because release doesn't bother
404 * incrementing if already positive.
405 *
406 */
407 else if (casReleaseStatus(p, releaseStatus,
408 (releaseStatus > 0)? 0 : -1) &&
409 releaseStatus <= 0) {
410
411 // Update and check timeout value
412 if (nanos > 0) {
413 long now = TimeUnit.nanoTime();
414 if (lastTime != 0) {
415 nanos -= now - lastTime;
416 if (nanos == 0) // avoid zero
417 nanos = -1;
418 }
419 lastTime = now;
420 }
421
422 if (nanos >= 0)
423 JSR166Support.park(false, nanos);
424
425 if (!interruptible) {
426 if (Thread.interrupted()) // consume interrupt for now
427 interrupted = true;
428 }
429 else if (nanos < 0 || current.isInterrupted()) {
430 node.thread = null; // disable signals
431 releaseStatusUpdater.set(node, CANCELLED); // don't need CAS here
432 signalSuccessor(node);
433 return false;
434 }
435 }
436 }
437 }
438
439 /**
440 * Wake up node's successor, if one exists
441 */
442 private void signalSuccessor(ReentrantLockQueueNode node) {
443 /*
444 * Find successor -- normally just node.next.
445 */
446 ReentrantLockQueueNode s = node.next;
447
448 /*
449 * if s is cancelled, traverse through next's.
450 */
451
452 while (s != null && s.releaseStatus == CANCELLED) {
453 node = s;
454 s = s.next;
455 }
456
457 /*
458 * If successor appears to be null, check to see if a newly
459 * queued node is successor by starting at tail and working
460 * backwards. If so, help out the enqueing thread by setting
461 * next field. We don't expect this loop to trigger often,
462 * and hardly ever to iterate.
463 */
464
465 if (s == null) {
466 ReentrantLockQueueNode t = tail;
467 for (;;) {
468 /*
469 * If t == node, there is no successor.
470 */
471 if (t == node)
472 return;
473
474 ReentrantLockQueueNode tp = t.prev;
475
476 /*
477 * t's predecessor is null if we are lagging so far
478 * behind the actions of other nodes/threads that an
479 * intervening head.prev was nulled by some
480 * non-cancelled successor of node. In which case,
481 * there's no live successor.
482 */
483
484 if (tp == null)
485 return;
486
487 /*
488 * If we find successor, we can do the assignment to
489 * next (don't even need CAS) on behalf of enqueuing
490 * thread. At worst we will stall now and lag behind
491 * both the setting and the later clearing of next
492 * field. But if so, we will reattach an internal link
493 * in soon-to-be unreachable set of nodes, so no harm
494 * done.
495 */
496
497 if (tp == node) {
498 node.next = s = t;
499 break;
500 }
501
502 t = tp;
503
504 /*
505 * Before iterating, check to see if link has
506 * appeared.
507 */
508 ReentrantLockQueueNode n = node.next;
509 if (n != null) {
510 s = n;
511 break;
512 }
513 }
514 }
515
516 Thread thr = s.thread;
517 if (thr != null && thr != owner) // don't bother signalling if has lock
518 JSR166Support.unpark(thr);
519 }
520
521
522 /**
523 * Increment releaseStatus and signal next thread in queue if one
524 * exists and is waiting. Called only by unlock. This code is split
525 * out from unlock to encourage inlining of non-contended cases.
526 */
527 private void releaseFirst() {
528 for (;;) {
529 ReentrantLockQueueNode h = head;
530 if (h == tail) // No successor
531 return;
532
533 int c = h.releaseStatus;
534 if (c > 0) // Don't need signal if already positive
535 return;
536 if (owner != null) // Don't bother if some thread got lock
537 return;
538
539 if (casReleaseStatus(h, c, (c < 0)? 0 : 1)) { // saturate at 1
540 if (c < 0)
541 signalSuccessor(h);
542 return;
543 }
544 // else retry if CAS fails
545 }
546 }
547
548 /**
549 * Attempts to release this lock. <p>If the current thread is the
550 * holder of this lock then the hold count is decremented. If the
551 * hold count is now zero then the lock is released. <p>If the
552 * current thread is not the holder of this lock then {@link
553 * IllegalMonitorStateException} is thrown.
554 * @throws IllegalMonitorStateException if the current thread does not
555 * hold this lock.
556 */
557 public void unlock() {
558 checkOwner(Thread.currentThread());
559 if (recursions > 0)
560 --recursions;
561 else {
562 ownerUpdater.set(this, null);
563 if (tail != this) // don't bother if never contended
564 releaseFirst();
565 }
566 }
567
568 /**
569 * Acquire the lock.
570 * <p>Acquires the lock if it is not held be another thread and returns
571 * immediately, setting the lock hold count to one.
572 * <p>If the current thread
573 * already holds the lock then the hold count is incremented by one and
574 * the method returns immediately.
575 * <p>If the lock is held by another thread then the
576 * the current thread thread becomes disabled for thread scheduling
577 * purposes and lies dormant until the lock has been acquired
578 * at which time the lock hold count is set to one.
579 */
580 public void lock() {
581 Thread current = Thread.currentThread();
582 if (!canBarge() || !acquireOwner(current))
583 doLock(current, null, false, 0);
584
585 }
586
587 /**
588 * Acquires the lock unless the current thread is
589 * {@link Thread#interrupt interrupted}.
590 * <p>Acquires the lock if it is not held by another thread and returns
591 * immediately, setting the lock hold count to one.
592 * <p>If the current thread already holds this lock then the hold count
593 * is incremented by one and the method returns immediately.
594 * <p>If the lock is held by another thread then the
595 * the current thread becomes disabled for thread scheduling
596 * purposes and lies dormant until one of two things happens:
597 * <ul>
598 * <li> The lock is acquired by the current thread; or
599 * <li> Some other thread {@link Thread#interrupt interrupts} the current
600 * thread.
601 * </ul>
602 * <p>If the lock is acquired by the current thread then the lock hold
603 * count is set to one.
604 * <p>If the current thread:
605 * <ul>
606 * <li>has its interrupted status set on entry to this method; or
607 * <li>is {@link Thread#interrupt interrupted} while waiting to acquire
608 * the lock,
609 * </ul>
610 * then {@link InterruptedException} is thrown and the current thread's
611 * interrupted status is cleared. As this method is an explicit
612 * interruption point, preference is given to responding to the interrupt
613 * over reentrant acquisition of the lock.
614 *
615 *
616 * @throws InterruptedException if the current thread is interrupted
617 */
618 public void lockInterruptibly() throws InterruptedException {
619 Thread current = Thread.currentThread();
620 if (Thread.interrupted() ||
621 (!canBarge() || !acquireOwner(current)) &&
622 !doLock(current, null, true, 0))
623 throw new InterruptedException();
624 }
625
626 /**
627 * Acquires the lock only if it is not held by another thread at the time
628 * of invocation.
629 * <p>Acquires the lock if it is not held by another thread and returns
630 * immediately with the value <tt>true</tt>, setting the lock hold count
631 * to one.
632 * <p> If the current thread
633 * already holds this lock then the hold count is incremented by one and
634 * the method returns <tt>true</tt>.
635 * <p>If the lock is held by another thread then this method will return
636 * immediately with the value <tt>false</tt>.
637 *
638 * @return <tt>true</tt>if the lock was free and was acquired by the
639 * current thread, or the lock was already held by the current thread; and
640 * <tt>false</tt> otherwise.
641 */
642 public boolean tryLock() {
643 Thread current = Thread.currentThread();
644 if (acquireOwner(current))
645 return true;
646 if (owner == current) {
647 ++recursions;
648 return true;
649 }
650 return false;
651 }
652
653 /**
654 *
655 * Acquires the lock if it is not held by another thread within the given
656 * waiting time and the current thread has not been interrupted.
657 * <p>Acquires the lock if it is not held by another thread and returns
658 * immediately with the value <tt>true</tt>, setting the lock hold count
659 * to one.
660 * <p> If the current thread
661 * already holds this lock then the hold count is incremented by one and
662 * the method returns <tt>true</tt>.
663 * <p>If the lock is held by another thread then the
664 * the current thread becomes disabled for thread scheduling
665 * purposes and lies dormant until one of three things happens:
666 * <ul>
667 * <li> The lock is acquired by the current thread; or
668 * <li> Some other thread {@link Thread#interrupt interrupts} the current
669 * thread; or
670 * <li> The specified waiting time elapses
671 * </ul>
672 * <p>If the lock is acquired then the value <tt>true</tt> is returned and
673 * the lock hold count is set to one.
674 * <p>If the current thread:
675 * <ul>
676 * <li>has its interrupted status set on entry to this method; or
677 * <li>is {@link Thread#interrupt interrupted} before acquiring
678 * the lock,
679 * </ul>
680 * then {@link InterruptedException} is thrown and the current thread's
681 * interrupted status is cleared. As this method is an explicit
682 * interruption point, preference is given to responding to the interrupt
683 * over reentrant acquisition of the lock.
684 * <p>If the specified waiting time elapses then the value <tt>false</tt>
685 * is returned.
686 * <p>The given waiting time is a best-effort lower bound. If the time is
687 * less than or equal to zero, the method will not wait at all.
688 *
689 *
690 * @return <tt>true</tt> if the lock was free and was acquired by the
691 * current thread, or the lock was already held by the current thread; and
692 * <tt>false</tt> if the waiting time elapsed before the lock could be
693 * acquired.
694 *
695 * @throws InterruptedException if the current thread is interrupted
696 */
697 public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
698 if (unit == null)
699 throw new NullPointerException();
700 if (Thread.interrupted())
701 throw new InterruptedException();
702 Thread current = Thread.currentThread();
703 if (canBarge() && acquireOwner(current))
704 return true;
705 if (owner == current) { // check recursions before timeout
706 ++recursions;
707 return true;
708 }
709 if (timeout <= 0)
710 return false;
711 if (doLock(current, null, true, unit.toNanos(timeout)))
712 return true;
713 if (Thread.interrupted())
714 throw new InterruptedException();
715 return false; // timed out
716 }
717
718
719 /**
720 * Queries the number of holds on this lock by the current thread.
721 * <p>A thread has a hold on a lock for each lock action that is not
722 * matched by an unlock action.
723 * <p>The hold count information is typically only used for testing and
724 * debugging purposes. For example, if a certain section of code should
725 * not be entered with the lock already held then we can assert that
726 * fact:
727 * <pre>
728 * class X {
729 * ReentrantLock lock = new ReentrantLock();
730 * // ...
731 *
732 * public void m() {
733 * assert lock.getHoldCount() == 0;
734 * lock.lock();
735 * try {
736 * // ... method body
737 * } finally {
738 * lock.unlock()
739 * }
740 * }
741 * }
742 * </pre>
743 *
744 * @return the number of holds on this lock by current thread,
745 * or zero if this lock is not held by current thread.
746 **/
747 public int getHoldCount() {
748 return (owner == Thread.currentThread()) ? recursions + 1 : 0;
749 }
750
751 /**
752 * Queries if this lock is held by the current thread.
753 * <p>Analogous to the {@link Thread#holdsLock} method for built-in
754 * monitor locks, this method is typically used for debugging and
755 * testing. For example, a method that should only be called while
756 * a lock is held can assert that this is the case:
757 * <pre>
758 * class X {
759 * ReentrantLock lock = new ReentrantLock();
760 * // ...
761 *
762 * public void m() {
763 * assert lock.isHeldByCurrentThread();
764 * // ... method body
765 * }
766 * }
767 * </pre>
768 *
769 * @return <tt>true</tt> if current thread holds this lock and
770 * <tt>false</tt> otherwise.
771 **/
772 public boolean isHeldByCurrentThread() {
773 return (owner == Thread.currentThread());
774 }
775
776
777 /**
778 * Queries if this lock is held by any thread. THis method is
779 * designed for use in monitoring, not for synchronization control.
780 * @return <tt>true</tt> if any thread holds this lock and
781 * <tt>false</tt> otherwise.
782 **/
783 public boolean isLocked() {
784 return owner != null;
785 }
786
787 /**
788 * Reconstitute by resetting head and tail to point back to the lock.
789 */
790 private void readObject(java.io.ObjectInputStream s)
791 throws java.io.IOException, ClassNotFoundException {
792 s.defaultReadObject();
793 head = tail = this;
794 }
795
796 /**
797 * Returns a {@link Condition} instance for use with this
798 * {@link Lock} instance.
799 *
800 * <p>The returned {@link Condition} instance has the same behavior and
801 * usage
802 * restrictions with this lock as the {@link Object} monitor methods
803 * ({@link Object#wait() wait}, {@link Object#notify notify}, and
804 * {@link Object#notifyAll notifyAll}) have with the built-in monitor
805 * lock:
806 * <ul>
807 * <li>If this lock is not held when any of the {@link Condition}
808 * {@link Condition#await() waiting} or {@link Condition#signal signalling}
809 * methods are called, then an {@link IllegalMonitorStateException} is
810 * thrown.
811 * <li>When the condition {@link Condition#await() waiting} methods are
812 * called the lock is released and before they return the lock is
813 * reacquired and the lock hold count restored to what it was when the
814 * method was called.
815 * <li>If a thread is {@link Thread#interrupt interrupted} while waiting
816 * then the wait will terminate, an {@link InterruptedException} will be
817 * thrown, and the thread's interrupted status will be cleared.
818 * <li>The order in which waiting threads are signalled is not specified.
819 * <li>The order in which threads returning from a wait, and threads trying
820 * to acquire the lock, are granted the lock, is not specified.
821 * </ul>
822 */
823 public Condition newCondition() {
824 return new ReentrantLockConditionObject();
825 }
826
827 // Helper methods for Conditions
828
829 /**
830 * Return true if a node, always one that was initially placed on
831 * a condition queue, is off the condition queue (and thus,
832 * normally is now on lock queue.)
833 */
834 boolean isOffConditionQueue(ReentrantLockQueueNode w) {
835 return w.releaseStatus > TRANSFERRING;
836 }
837
838 /**
839 * Transfer a node from a condition queue onto lock queue.
840 * Return true if successful (i.e., node not cancelled)
841 */
842 final boolean transferToLockQueue(ReentrantLockQueueNode node) {
843 /*
844 * Atomically change status to TRANSFERRING to avoid races
845 * with cancelling waiters. We use a special value that causes
846 * any waiters spuriously waking up to re-park until the node
847 * has been placed on lock queue.
848 */
849 if (!casReleaseStatus(node, ON_CONDITION_QUEUE, TRANSFERRING))
850 return false;
851
852 /*
853 * Splice onto queue
854 */
855 ReentrantLockQueueNode p = enq(node);
856
857 /*
858 * Establish normal lock-queue releaseStatus for node. The
859 * CAS can fail if node already was involved in a cancellation
860 * on lock-queue, in which case we signal to be sure.
861 */
862 if (!casReleaseStatus(node, TRANSFERRING, 0))
863 signalSuccessor(node);
864
865 /*
866 * Ensure releaseStatus of predecessor is negative to indicate
867 * that thread is (probably) waiting. If attempt to set releaseStatus
868 * fails or is pred is/becomes cancelled, wake up successor
869 * (which will ordinarily be "node") to resynch.
870 */
871
872 for (;;) {
873 int c = p.releaseStatus;
874 if (c < 0 || (c != CANCELLED && casReleaseStatus(p, c, -1)))
875 break;
876 signalSuccessor(p);
877 if (c == CANCELLED)
878 break;
879 }
880
881 return true;
882 }
883
884 /**
885 * Hook method used by ReentrantReadWriteLock. Called
886 * before unlocking lock to enter wait.
887 */
888 void beforeWait() { }
889
890
891 /**
892 * Hook method used by ReentrantReadWriteLock. Called
893 * after locking lock after exiting wait.
894 */
895 void afterWait() { }
896
897 private class ReentrantLockConditionObject implements Condition, java.io.Serializable {
898 /*
899 * Because condition queues are accessed only when locks are
900 * already held, we just need a simple linked queue to hold
901 * nodes while they are waiting on conditions. They are then
902 * transferred to the lock queue to re-acquire locks.
903 */
904
905 /**
906 * First node of condition queue.
907 */
908 private transient ReentrantLockQueueNode firstWaiter;
909
910 /**
911 * Last node of condition queue.
912 */
913 private transient ReentrantLockQueueNode lastWaiter;
914
915 /**
916 * Basic linked queue insertion.
917 */
918 private ReentrantLockQueueNode addWaiter(Thread current) {
919 ReentrantLockQueueNode w = new ReentrantLockQueueNode(current);
920 w.releaseStatus = ON_CONDITION_QUEUE;
921 if (lastWaiter == null)
922 firstWaiter = lastWaiter = w;
923 else {
924 ReentrantLockQueueNode t = lastWaiter;
925 lastWaiter = w;
926 t.next = w;
927 }
928 return w;
929 }
930
931 /**
932 * Main code for signal. Dequeue and transfer nodes until hit
933 * non-cancelled one or null. Split out from signal to
934 * encourage compilers to inline the case of no waiters.
935 */
936 private void doSignal(ReentrantLockQueueNode first) {
937 do {
938 if ( (firstWaiter = first.next) == null)
939 lastWaiter = null;
940 first.next = null;
941 if (transferToLockQueue(first))
942 return;
943 first = firstWaiter;
944 } while (first != null);
945 }
946
947 public void signal() {
948 checkOwner(Thread.currentThread());
949 ReentrantLockQueueNode w = firstWaiter;
950 if (w != null)
951 doSignal(w);
952 }
953
954 public void signalAll() {
955 checkOwner(Thread.currentThread());
956 // Pull off list all at once and traverse.
957 ReentrantLockQueueNode w = firstWaiter;
958 if (w != null) {
959 lastWaiter = firstWaiter = null;
960 do {
961 ReentrantLockQueueNode n = w.next;
962 w.next = null;
963 transferToLockQueue(w);
964 w = n;
965 } while (w != null);
966 }
967 }
968
969 /*
970 * Various flavors of wait. Each almost the same, but
971 * annoyingly different and no nice way to factor common code.
972 */
973
974 public void await() throws InterruptedException {
975 Thread current = Thread.currentThread();
976 checkOwner(current);
977
978 ReentrantLockQueueNode w = addWaiter(current);
979 beforeWait();
980 int recs = recursions;
981 unlock();
982
983 boolean wasInterrupted = false;
984
985 while (!isOffConditionQueue(w)) {
986 JSR166Support.park(false, 0);
987 if (Thread.interrupted()) {
988 wasInterrupted = true;
989 if (casReleaseStatus(w, ON_CONDITION_QUEUE, CANCELLED)) {
990 w.thread = null;
991 w = null;
992 }
993 break;
994 }
995 }
996
997 /*
998 * If we exited above loop due to cancellation, then w is
999 * null, and doLock will make a new lock node for
1000 * us. Otherwise, upon exit, our node is already in the
1001 * lock queue when doLock is called.
1002 */
1003 doLock(current, w, false, 0);
1004
1005 recursions = recs;
1006 afterWait();
1007
1008 if (wasInterrupted || Thread.interrupted())
1009 throw new InterruptedException();
1010 }
1011
1012 public void awaitUninterruptibly() {
1013 Thread current = Thread.currentThread();
1014 checkOwner(current);
1015
1016 ReentrantLockQueueNode w = addWaiter(current);
1017 beforeWait();
1018 int recs = recursions;
1019 unlock();
1020
1021 boolean wasInterrupted = false;
1022 while (!isOffConditionQueue(w)) {
1023 JSR166Support.park(false, 0);
1024 if (Thread.interrupted())
1025 wasInterrupted = true;
1026 }
1027
1028 doLock(current, w, false, 0);
1029 recursions = recs;
1030 afterWait();
1031 // avoid re-interrupts on exit
1032 if (wasInterrupted && !current.isInterrupted())
1033 current.interrupt();
1034 }
1035
1036
1037 public long awaitNanos(long nanos) throws InterruptedException {
1038 Thread current = Thread.currentThread();
1039 checkOwner(current);
1040
1041 ReentrantLockQueueNode w = addWaiter(current);
1042 beforeWait();
1043 int recs = recursions;
1044 unlock();
1045
1046 if (nanos <= 0) nanos = 1; // park arg must be positive
1047 long timeLeft = nanos;
1048 long startTime = TimeUnit.nanoTime();
1049 boolean wasInterrupted = false;
1050 boolean cancelled = false;
1051
1052 if (!isOffConditionQueue(w)) {
1053 for (;;) {
1054 JSR166Support.park(false, timeLeft);
1055 if (Thread.interrupted())
1056 wasInterrupted = true;
1057 else if (isOffConditionQueue(w))
1058 break;
1059 else
1060 timeLeft = nanos - (TimeUnit.nanoTime() - startTime);
1061
1062 if (wasInterrupted || timeLeft <= 0) {
1063 if (casReleaseStatus(w, ON_CONDITION_QUEUE, CANCELLED)) {
1064 w.thread = null;
1065 w = null;
1066 }
1067 break;
1068 }
1069 }
1070 }
1071
1072 doLock(current, w, false, 0);
1073 recursions = recs;
1074 afterWait();
1075
1076 if (wasInterrupted || Thread.interrupted())
1077 throw new InterruptedException();
1078 else if (timeLeft <= 0)
1079 return timeLeft;
1080 else
1081 return nanos - (TimeUnit.nanoTime() - startTime);
1082 }
1083
1084 public boolean awaitUntil(Date deadline) throws InterruptedException {
1085 Thread current = Thread.currentThread();
1086 checkOwner(current);
1087
1088 ReentrantLockQueueNode w = addWaiter(current);
1089 beforeWait();
1090 int recs = recursions;
1091 unlock();
1092
1093 boolean wasInterrupted = false;
1094 boolean cancelled = false;
1095 long abstime = deadline.getTime();
1096
1097 if (!isOffConditionQueue(w)) {
1098 for (;;) {
1099 JSR166Support.park(true, abstime);
1100
1101 boolean timedOut = false;
1102 if (Thread.interrupted())
1103 wasInterrupted = true;
1104 else if (isOffConditionQueue(w))
1105 break;
1106 else if (System.currentTimeMillis() <= abstime)
1107 timedOut = true;
1108
1109 if (wasInterrupted || timedOut) {
1110 if (casReleaseStatus(w, ON_CONDITION_QUEUE, CANCELLED)) {
1111 w.thread = null;
1112 w = null;
1113 }
1114 break;
1115 }
1116 }
1117 }
1118
1119 doLock(current, w, false, 0);
1120 recursions = recs;
1121 afterWait();
1122
1123 if (wasInterrupted || Thread.interrupted())
1124 throw new InterruptedException();
1125 return !cancelled;
1126 }
1127
1128 public boolean await(long time, TimeUnit unit) throws InterruptedException {
1129 return awaitNanos(unit.toNanos(time)) > 0;
1130 }
1131
1132 }
1133
1134 }
1135
1136 /**
1137 * Node class for threads waiting for locks. This cannot be nested
1138 * inside ReentrantLock because of Java inheritance circularity rules.
1139 */
1140 class ReentrantLockQueueNode {
1141 /**
1142 * Controls whether successor node is allowed to try to obtain
1143 * ownership. Acts as a saturating (in both directions) counting
1144 * semaphore: Upon each wait, the releaseStatus is reduced to zero
1145 * if positive, else reduced to negative, in which case the thread
1146 * will park. The releaseStatus is incremented on each unlock that
1147 * would enable successor thread to obtain lock (succeeding if
1148 * there is no contention). The special value of CANCELLED is used
1149 * to mean that the releaseStatus cannot be either incremented or
1150 * decremented. The special value of ON_CONDITION_QUEUE is used
1151 * when nodes are on conditions queues instead of lock queue, and
1152 * the special value TRANSFERRING is used while signals are in
1153 * progress.
1154 */
1155 transient volatile int releaseStatus;
1156
1157 /**
1158 * Link to predecessor node that current node/thread relies on
1159 * for checking releaseStatus. Assigned once during enqueing,
1160 * and nulled out (for sake of GC) only upon dequeuing. Upon
1161 * cancellation, we do NOT adjust this field, but simply
1162 * traverse through prev's until we hit a non-cancelled node.
1163 * A valid predecessor will always exist because the head node
1164 * is never cancelled.
1165 */
1166 transient volatile ReentrantLockQueueNode prev;
1167
1168 /**
1169 * Link to the successor node that the current node/thread
1170 * unparks upon lock release. Assigned once during enquing.
1171 * Upon cancellation, we do NOT adjust this field, but simply
1172 * traverse through next's until we hit a non-cancelled node,
1173 * (or null if at end of queue). The enqueue operation does
1174 * not assign next field of a predecessor until after
1175 * attachment, so seeing a null next field not necessarily
1176 * mean that node is at end of queue. However, if a next field
1177 * appears to be null, we can scan prev's from the tail to
1178 * double-check.
1179 */
1180 transient volatile ReentrantLockQueueNode next;
1181
1182 /**
1183 * The thread that enqueued this node. Initialized on
1184 * construction and nulled out after use. Note that this need
1185 * not be declared volatile since it is always accessed after
1186 * traversing volatile links, and written before writing
1187 * links.
1188 */
1189 transient Thread thread;
1190
1191 ReentrantLockQueueNode() { }
1192 ReentrantLockQueueNode(Thread t) { thread = t; }
1193 }