KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > util > concurrent > locks > ReentrantReadWriteLock


1 /*
2  * @(#)ReentrantReadWriteLock.java 1.7 04/07/14
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.util.concurrent.locks;
9 import java.util.concurrent.*;
10 import java.util.concurrent.atomic.*;
11 import java.util.*;
12
13 /**
14  * An implementation of {@link ReadWriteLock} supporting similar
15  * semantics to {@link ReentrantLock}.
16  * <p>This class has the following properties:
17  *
18  * <ul>
19  * <li><b>Acquisition order</b>
20  *
21  * <p> This class does not impose a reader or writer preference
22  * ordering for lock access. However, it does support an optional
23  * <em>fairness</em> policy. When constructed as fair, threads
24  * contend for entry using an approximately arrival-order policy. When
25  * the write lock is released either the longest-waiting single writer
26  * will be assigned the write lock, or if there is a reader waiting
27  * longer than any writer, the set of readers will be assigned the
28  * read lock. When constructed as non-fair, the order of entry to the
29  * lock need not be in arrival order. In either case, if readers are
30  * active and a writer enters the lock then no subsequent readers will
31  * be granted the read lock until after that writer has acquired and
32  * released the write lock.
33  *
34  * <li><b>Reentrancy</b>
35  * <p>This lock allows both readers and writers to reacquire read or
36  * write locks in the style of a {@link ReentrantLock}. Readers are not
37  * allowed until all write locks held by the writing thread have been
38  * released.
39  * <p>Additionally, a writer can acquire the read lock - but not vice-versa.
40  * Among other applications, reentrancy can be useful when
41  * write locks are held during calls or callbacks to methods that
42  * perform reads under read locks.
43  * If a reader tries to acquire the write lock it will never succeed.
44  *
45  * <li><b>Lock downgrading</b>
46  * <p>Reentrancy also allows downgrading from the write lock to a read lock,
47  * by acquiring the write lock, then the read lock and then releasing the
48  * write lock. However, upgrading from a read lock to the write lock is
49  * <b>not</b> possible.
50  *
51  * <li><b>Interruption of lock acquisition</b>
52  * <p>The read lock and write lock both support interruption during lock
53  * acquisition.
54  *
55  * <li><b>{@link Condition} support</b>
56  * <p>The write lock provides a {@link Condition} implementation that
57  * behaves in the same way, with respect to the write lock, as the
58  * {@link Condition} implementation provided by
59  * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
60  * This {@link Condition} can, of course, only be used with the write lock.
61  * <p>The read lock does not support a {@link Condition} and
62  * <tt>readLock().newCondition()</tt> throws
63  * <tt>UnsupportedOperationException</tt>.
64  *
65  * <li><b>Instrumentation</b>
66  * <P> This class supports methods to determine whether locks
67  * are held or contended. These methods are designed for monitoring
68  * system state, not for synchronization control.
69  * </ul>
70  *
71  * <p> Serialization of this class behaves in the same way as built-in
72  * locks: a deserialized lock is in the unlocked state, regardless of
73  * its state when serialized.
74  *
75  * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
76  * reentrancy to perform lock downgrading after updating a cache (exception
77  * handling is elided for simplicity):
78  * <pre>
79  * class CachedData {
80  * Object data;
81  * volatile boolean cacheValid;
82  * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
83  *
84  * void processCachedData() {
85  * rwl.readLock().lock();
86  * if (!cacheValid) {
87  * // upgrade lock manually
88  * rwl.readLock().unlock(); // must unlock first to obtain writelock
89  * rwl.writeLock().lock();
90  * if (!cacheValid) { // recheck
91  * data = ...
92  * cacheValid = true;
93  * }
94  * // downgrade lock
95  * rwl.readLock().lock(); // reacquire read without giving up write lock
96  * rwl.writeLock().unlock(); // unlock write, still hold read
97  * }
98  *
99  * use(data);
100  * rwl.readLock().unlock();
101  * }
102  * }
103  * </pre>
104  *
105  * ReentrantReadWriteLocks can be used to improve concurrency in some
106  * uses of some kinds of Collections. This is typically worthwhile
107  * only when the collections are expected to be large, accessed by
108  * more reader threads than writer threads, and entail operations with
109  * overhead that outweighs synchronization overhead. For example, here
110  * is a class using a TreeMap that is expected to be large and
111  * concurrently accessed.
112  *
113  * <pre>
114  * class RWDictionary {
115  * private final Map&lt;String, Data&gt; m = new TreeMap&lt;String, Data&gt;();
116  * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
117  * private final Lock r = rwl.readLock();
118  * private final Lock w = rwl.writeLock();
119  *
120  * public Data get(String key) {
121  * r.lock(); try { return m.get(key); } finally { r.unlock(); }
122  * }
123  * public String[] allKeys() {
124  * r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }
125  * }
126  * public Data put(String key, Data value) {
127  * w.lock(); try { return m.put(key, value); } finally { w.unlock(); }
128  * }
129  * public void clear() {
130  * w.lock(); try { m.clear(); } finally { w.unlock(); }
131  * }
132  * }
133  * </pre>
134  *
135  *
136  * <h3>Implementation Notes</h3>
137  *
138  * <p>A reentrant write lock intrinsically defines an owner and can
139  * only be released by the thread that acquired it. In contrast, in
140  * this implementation, the read lock has no concept of ownership, and
141  * there is no requirement that the thread releasing a read lock is
142  * the same as the one that acquired it. However, this property is
143  * not guaranteed to hold in future implementations of this class.
144  *
145  * <p> This lock supports a maximum of 65536 recursive write locks
146  * and 65536 read locks. Attempts to exceed these limits result in
147  * {@link Error} throws from locking methods.
148  *
149  * @since 1.5
150  * @author Doug Lea
151  *
152  */

153 public class ReentrantReadWriteLock implements ReadWriteLock JavaDoc, java.io.Serializable JavaDoc {
154     private static final long serialVersionUID = -6992448646407690164L;
155     /** Inner class providing readlock */
156     private final ReentrantReadWriteLock.ReadLock JavaDoc readerLock;
157     /** Inner class providing writelock */
158     private final ReentrantReadWriteLock.WriteLock JavaDoc writerLock;
159     /** Performs all synchronization mechanics */
160     private final Sync sync;
161
162     /**
163      * Creates a new <tt>ReentrantReadWriteLock</tt> with
164      * default ordering properties.
165      */

166     public ReentrantReadWriteLock() {
167         sync = new NonfairSync();
168         readerLock = new ReadLock(this);
169         writerLock = new WriteLock(this);
170     }
171
172     /**
173      * Creates a new <tt>ReentrantReadWriteLock</tt> with
174      * the given fairness policy.
175      *
176      * @param fair true if this lock should use a fair ordering policy
177      */

178     public ReentrantReadWriteLock(boolean fair) {
179         sync = (fair)? new FairSync() : new NonfairSync();
180         readerLock = new ReadLock(this);
181         writerLock = new WriteLock(this);
182     }
183
184     public ReentrantReadWriteLock.WriteLock JavaDoc writeLock() { return writerLock; }
185     public ReentrantReadWriteLock.ReadLock JavaDoc readLock() { return readerLock; }
186
187     /*
188      * Read vs write count extraction constants and functions.
189      * Lock state is logically divided into two shorts: The lower
190      * one representing the exclusive (writer) lock hold count,
191      * and the upper the shared (reader) hold count.
192      */

193     
194     static final int SHARED_SHIFT = 16;
195     static final int SHARED_UNIT = (1 << SHARED_SHIFT);
196     static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
197     
198     /** Returns the number of shared holds represented in count */
199     static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
200     /** Returns the number of exclusive holds represented in count */
201     static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
202
203     /**
204      * Synchronization implementation for ReentrantReadWriteLock.
205      * Subclassed into fair and nonfair versions.
206      */

207     abstract static class Sync extends AbstractQueuedSynchronizer JavaDoc {
208         /** Current (exclusive) owner thread */
209         transient Thread JavaDoc owner;
210
211         /**
212          * Perform write lock. Allows fast path in non-fair version.
213          */

214         abstract void wlock();
215
216         /**
217          * Perform non-fair tryLock for write. tryAcquire is
218          * implemented in subclasses, but both versions need nonfair
219          * try for trylock method
220          */

221         final boolean nonfairTryAcquire(int acquires) {
222             // mask out readlocks if called from condition methods
223
acquires = exclusiveCount(acquires);
224             Thread JavaDoc current = Thread.currentThread();
225             int c = getState();
226             int w = exclusiveCount(c);
227             if (w + acquires >= SHARED_UNIT)
228                 throw new Error JavaDoc("Maximum lock count exceeded");
229             if (c != 0 && (w == 0 || current != owner))
230                 return false;
231             if (!compareAndSetState(c, c + acquires))
232                 return false;
233             owner = current;
234             return true;
235         }
236
237         /**
238          * Perform nonfair tryLock for read.
239          */

240         final int nonfairTryAcquireShared(int acquires) {
241             for (;;) {
242                 int c = getState();
243                 int nextc = c + (acquires << SHARED_SHIFT);
244                 if (nextc < c)
245                     throw new Error JavaDoc("Maximum lock count exceeded");
246                 if (exclusiveCount(c) != 0 &&
247                     owner != Thread.currentThread())
248                     return -1;
249                 if (compareAndSetState(c, nextc))
250                     return 1;
251                 // Recheck count if lost CAS
252
}
253         }
254
255         protected final boolean tryRelease(int releases) {
256             Thread JavaDoc current = Thread.currentThread();
257             int c = getState();
258             if (owner != current)
259                 throw new IllegalMonitorStateException JavaDoc();
260             int nextc = c - releases;
261             boolean free = false;
262             if (exclusiveCount(c) == releases) {
263                 free = true;
264                 owner = null;
265             }
266             setState(nextc);
267             return free;
268         }
269
270         protected final boolean tryReleaseShared(int releases) {
271             for (;;) {
272                 int c = getState();
273                 int nextc = c - (releases << SHARED_SHIFT);
274                 if (nextc < 0)
275                     throw new IllegalMonitorStateException JavaDoc();
276                 if (compareAndSetState(c, nextc))
277                     return nextc == 0;
278             }
279         }
280     
281         protected final boolean isHeldExclusively() {
282             return exclusiveCount(getState()) != 0 &&
283                 owner == Thread.currentThread();
284         }
285
286         // Methods relayed to outer class
287

288         final ConditionObject newCondition() {
289             return new ConditionObject();
290         }
291
292         final Thread JavaDoc getOwner() {
293             int c = exclusiveCount(getState());
294             Thread JavaDoc o = owner;
295             return (c == 0)? null : o;
296         }
297         
298         final int getReadLockCount() {
299             return sharedCount(getState());
300         }
301         
302         final boolean isWriteLocked() {
303             return exclusiveCount(getState()) != 0;
304         }
305
306         final int getWriteHoldCount() {
307             int c = exclusiveCount(getState());
308             Thread JavaDoc o = owner;
309             return (o == Thread.currentThread())? c : 0;
310         }
311
312         /**
313          * Reconstitute this lock instance from a stream
314          * @param s the stream
315          */

316         private void readObject(java.io.ObjectInputStream JavaDoc s)
317             throws java.io.IOException JavaDoc, ClassNotFoundException JavaDoc {
318             s.defaultReadObject();
319             setState(0); // reset to unlocked state
320
}
321
322         final int getCount() { return getState(); }
323     }
324
325     /**
326      * Nonfair version of Sync
327      */

328     final static class NonfairSync extends Sync {
329         protected final boolean tryAcquire(int acquires) {
330             return nonfairTryAcquire(acquires);
331         }
332
333         protected final int tryAcquireShared(int acquires) {
334             return nonfairTryAcquireShared(acquires);
335         }
336
337         // Use fastpath for main write lock method
338
final void wlock() {
339             if (compareAndSetState(0, 1))
340                 owner = Thread.currentThread();
341             else
342                 acquire(1);
343         }
344     }
345
346     /**
347      * Fair version of Sync
348      */

349     final static class FairSync extends Sync {
350         protected final boolean tryAcquire(int acquires) {
351             // mask out readlocks if called from condition methods
352
acquires = exclusiveCount(acquires);
353             Thread JavaDoc current = Thread.currentThread();
354             Thread JavaDoc first;
355             int c = getState();
356             int w = exclusiveCount(c);
357             if (w + acquires >= SHARED_UNIT)
358                 throw new Error JavaDoc("Maximum lock count exceeded");
359             if ((w == 0 || current != owner) &&
360                 (c != 0 ||
361                  ((first = getFirstQueuedThread()) != null &&
362                   first != current)))
363                 return false;
364             if (!compareAndSetState(c, c + acquires))
365                 return false;
366             owner = current;
367             return true;
368         }
369
370         protected final int tryAcquireShared(int acquires) {
371             Thread JavaDoc current = Thread.currentThread();
372             for (;;) {
373                 int c = getState();
374                 if (exclusiveCount(c) != 0) {
375                     if (owner != current)
376                         return -1;
377                 } else {
378             Thread JavaDoc first = getFirstQueuedThread();
379             if (first != null && first != current)
380             return -1;
381         }
382                 int nextc = c + (acquires << SHARED_SHIFT);
383                 if (nextc < c)
384                     throw new Error JavaDoc("Maximum lock count exceeded");
385                 if (compareAndSetState(c, nextc))
386                     return 1;
387                 // Recheck count if lost CAS
388
}
389         }
390
391         final void wlock() { // no fast path
392
acquire(1);
393         }
394     }
395
396     /**
397      * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
398      */

399     public static class ReadLock implements Lock JavaDoc, java.io.Serializable JavaDoc {
400         private static final long serialVersionUID = -5992448646407690164L;
401         private final Sync sync;
402
403         /**
404          * Constructor for use by subclasses
405          * @param lock the outer lock object
406          * @throws NullPointerException if lock null
407          */

408         protected ReadLock(ReentrantReadWriteLock JavaDoc lock) {
409             sync = lock.sync;
410         }
411
412         /**
413          * Acquires the read lock.
414          *
415          * <p>Acquires the read lock if the write lock is not held by
416          * another thread and returns immediately.
417          *
418          * <p>If the write lock is held by another thread then
419          * the current thread becomes disabled for thread scheduling
420          * purposes and lies dormant until the read lock has been acquired.
421          */

422         public void lock() {
423             sync.acquireShared(1);
424         }
425
426         /**
427          * Acquires the read lock unless the current thread is
428          * {@link Thread#interrupt interrupted}.
429          *
430          * <p>Acquires the read lock if the write lock is not held
431          * by another thread and returns immediately.
432          *
433          * <p>If the write lock is held by another thread then the
434          * current thread becomes disabled for thread scheduling
435          * purposes and lies dormant until one of two things happens:
436          *
437          * <ul>
438          *
439          * <li>The read lock is acquired by the current thread; or
440          *
441          * <li>Some other thread {@link Thread#interrupt interrupts}
442          * the current thread.
443          *
444          * </ul>
445          *
446          * <p>If the current thread:
447          *
448          * <ul>
449          *
450          * <li>has its interrupted status set on entry to this method; or
451          *
452          * <li>is {@link Thread#interrupt interrupted} while acquiring
453          * the read lock,
454          *
455          * </ul>
456          *
457          * then {@link InterruptedException} is thrown and the current
458          * thread's interrupted status is cleared.
459          *
460          * <p>In this implementation, as this method is an explicit
461          * interruption point, preference is given to responding to
462          * the interrupt over normal or reentrant acquisition of the
463          * lock.
464          *
465          * @throws InterruptedException if the current thread is interrupted
466          */

467         public void lockInterruptibly() throws InterruptedException JavaDoc {
468             sync.acquireSharedInterruptibly(1);
469         }
470
471         /**
472          * Acquires the read lock only if the write lock is not held by
473          * another thread at the time of invocation.
474          *
475          * <p>Acquires the read lock if the write lock is not held by
476          * another thread and returns immediately with the value
477          * <tt>true</tt>. Even when this lock has been set to use a
478          * fair ordering policy, a call to <tt>tryLock()</tt>
479          * <em>will</em> immediately acquire the read lock if it is
480          * available, whether or not other threads are currently
481          * waiting for the read lock. This &quot;barging&quot; behavior
482          * can be useful in certain circumstances, even though it
483          * breaks fairness. If you want to honor the fairness setting
484          * for this lock, then use {@link #tryLock(long, TimeUnit)
485          * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
486          * (it also detects interruption).
487          *
488          * <p>If the write lock is held by another thread then
489          * this method will return immediately with the value
490          * <tt>false</tt>.
491          *
492          * @return <tt>true</tt> if the read lock was acquired.
493          */

494         public boolean tryLock() {
495             return sync.nonfairTryAcquireShared(1) >= 0;
496         }
497
498         /**
499          * Acquires the read lock if the write lock is not held by
500          * another thread within the given waiting time and the
501          * current thread has not been {@link Thread#interrupt
502          * interrupted}.
503          *
504          * <p>Acquires the read lock if the write lock is not held by
505          * another thread and returns immediately with the value
506          * <tt>true</tt>. If this lock has been set to use a fair
507          * ordering policy then an available lock <em>will not</em> be
508          * acquired if any other threads are waiting for the
509          * lock. This is in contrast to the {@link #tryLock()}
510          * method. If you want a timed <tt>tryLock</tt> that does
511          * permit barging on a fair lock then combine the timed and
512          * un-timed forms together:
513          *
514          * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
515          * </pre>
516          *
517          * <p>If the write lock is held by another thread then the
518          * current thread becomes disabled for thread scheduling
519          * purposes and lies dormant until one of three things happens:
520          *
521          * <ul>
522          *
523          * <li>The read lock is acquired by the current thread; or
524          *
525          * <li>Some other thread {@link Thread#interrupt interrupts} the current
526          * thread; or
527          *
528          * <li>The specified waiting time elapses
529          *
530          * </ul>
531          *
532          * <p>If the read lock is acquired then the value <tt>true</tt> is
533          * returned.
534          *
535          * <p>If the current thread:
536          *
537          * <ul>
538          *
539          * <li>has its interrupted status set on entry to this method; or
540          *
541          * <li>is {@link Thread#interrupt interrupted} while acquiring
542          * the read lock,
543          *
544          * </ul> then {@link InterruptedException} is thrown and the
545          * current thread's interrupted status is cleared.
546          *
547          * <p>If the specified waiting time elapses then the value
548          * <tt>false</tt> is returned. If the time is less than or
549          * equal to zero, the method will not wait at all.
550          *
551          * <p>In this implementation, as this method is an explicit
552          * interruption point, preference is given to responding to
553          * the interrupt over normal or reentrant acquisition of the
554          * lock, and over reporting the elapse of the waiting time.
555          *
556          * @param timeout the time to wait for the read lock
557          * @param unit the time unit of the timeout argument
558          *
559          * @return <tt>true</tt> if the read lock was acquired.
560          *
561          * @throws InterruptedException if the current thread is interrupted
562          * @throws NullPointerException if unit is null
563          *
564          */

565         public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException JavaDoc {
566             return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
567         }
568
569         /**
570          * Attempts to release this lock.
571          *
572          * <p> If the number of readers is now zero then the lock
573          * is made available for write lock attempts.
574          */

575         public void unlock() {
576             sync.releaseShared(1);
577         }
578
579         /**
580          * Throws <tt>UnsupportedOperationException</tt> because
581      * <tt>ReadLocks</tt> do not support conditions.
582          * @throws UnsupportedOperationException always
583          */

584         public Condition JavaDoc newCondition() {
585             throw new UnsupportedOperationException JavaDoc();
586         }
587
588         /**
589          * Returns a string identifying this lock, as well as its lock state.
590          * The state, in brackets, includes the String
591          * &quot;Read locks =&quot; followed by the number of held
592          * read locks.
593          * @return a string identifying this lock, as well as its lock state.
594          */

595         public String JavaDoc toString() {
596             int r = sync.getReadLockCount();
597             return super.toString() +
598                 "[Read locks = " + r + "]";
599         }
600
601     }
602
603     /**
604      * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
605      */

606     public static class WriteLock implements Lock JavaDoc, java.io.Serializable JavaDoc {
607         private static final long serialVersionUID = -4992448646407690164L;
608     private final Sync sync;
609
610         /**
611          * Constructor for use by subclasses
612          * @param lock the outer lock object
613          * @throws NullPointerException if lock null
614          */

615         protected WriteLock(ReentrantReadWriteLock JavaDoc lock) {
616             sync = lock.sync;
617         }
618
619         /**
620          * Acquire the write lock.
621          *
622          * <p>Acquires the write lock if neither the read nor write lock
623      * are held by another thread
624          * and returns immediately, setting the write lock hold count to
625          * one.
626          *
627          * <p>If the current thread already holds the write lock then the
628          * hold count is incremented by one and the method returns
629          * immediately.
630          *
631          * <p>If the lock is held by another thread then the current
632          * thread becomes disabled for thread scheduling purposes and
633          * lies dormant until the write lock has been acquired, at which
634          * time the write lock hold count is set to one.
635          */

636         public void lock() {
637             sync.wlock();
638         }
639
640         /**
641          * Acquires the write lock unless the current thread is {@link
642          * Thread#interrupt interrupted}.
643          *
644          * <p>Acquires the write lock if neither the read nor write lock
645      * are held by another thread
646          * and returns immediately, setting the write lock hold count to
647          * one.
648          *
649          * <p>If the current thread already holds this lock then the
650          * hold count is incremented by one and the method returns
651          * immediately.
652          *
653          * <p>If the lock is held by another thread then the current
654          * thread becomes disabled for thread scheduling purposes and
655          * lies dormant until one of two things happens:
656          *
657          * <ul>
658          *
659          * <li>The write lock is acquired by the current thread; or
660          *
661          * <li>Some other thread {@link Thread#interrupt interrupts}
662          * the current thread.
663          *
664          * </ul>
665          *
666          * <p>If the write lock is acquired by the current thread then the
667          * lock hold count is set to one.
668          *
669          * <p>If the current thread:
670          *
671          * <ul>
672          *
673          * <li>has its interrupted status set on entry to this method;
674          * or
675          *
676          * <li>is {@link Thread#interrupt interrupted} while acquiring
677          * the write lock,
678          *
679          * </ul>
680          *
681          * then {@link InterruptedException} is thrown and the current
682          * thread's interrupted status is cleared.
683          *
684          * <p>In this implementation, as this method is an explicit
685          * interruption point, preference is given to responding to
686          * the interrupt over normal or reentrant acquisition of the
687          * lock.
688          *
689          * @throws InterruptedException if the current thread is interrupted
690          */

691         public void lockInterruptibly() throws InterruptedException JavaDoc {
692             sync.acquireInterruptibly(1);
693         }
694
695         /**
696          * Acquires the write lock only if it is not held by another thread
697          * at the time of invocation.
698          *
699          * <p>Acquires the write lock if neither the read nor write lock
700      * are held by another thread
701          * and returns immediately with the value <tt>true</tt>,
702          * setting the write lock hold count to one. Even when this lock has
703          * been set to use a fair ordering policy, a call to
704          * <tt>tryLock()</tt> <em>will</em> immediately acquire the
705          * lock if it is available, whether or not other threads are
706          * currently waiting for the write lock. This &quot;barging&quot;
707          * behavior can be useful in certain circumstances, even
708          * though it breaks fairness. If you want to honor the
709          * fairness setting for this lock, then use {@link
710          * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
711          * which is almost equivalent (it also detects interruption).
712          *
713          * <p> If the current thread already holds this lock then the
714          * hold count is incremented by one and the method returns
715          * <tt>true</tt>.
716          *
717          * <p>If the lock is held by another thread then this method
718          * will return immediately with the value <tt>false</tt>.
719          *
720          * @return <tt>true</tt> if the lock was free and was acquired
721          * by the current thread, or the write lock was already held
722          * by the current thread; and <tt>false</tt> otherwise.
723          */

724         public boolean tryLock( ) {
725             return sync.nonfairTryAcquire(1);
726         }
727
728         /**
729          * Acquires the write lock if it is not held by another thread
730          * within the given waiting time and the current thread has
731          * not been {@link Thread#interrupt interrupted}.
732          *
733          * <p>Acquires the write lock if neither the read nor write lock
734      * are held by another thread
735          * and returns immediately with the value <tt>true</tt>,
736          * setting the write lock hold count to one. If this lock has been
737          * set to use a fair ordering policy then an available lock
738          * <em>will not</em> be acquired if any other threads are
739          * waiting for the write lock. This is in contrast to the {@link
740          * #tryLock()} method. If you want a timed <tt>tryLock</tt>
741          * that does permit barging on a fair lock then combine the
742          * timed and un-timed forms together:
743          *
744          * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
745          * </pre>
746          *
747          * <p>If the current thread already holds this lock then the
748          * hold count is incremented by one and the method returns
749          * <tt>true</tt>.
750          *
751          * <p>If the lock is held by another thread then the current
752          * thread becomes disabled for thread scheduling purposes and
753          * lies dormant until one of three things happens:
754          *
755          * <ul>
756          *
757          * <li>The write lock is acquired by the current thread; or
758          *
759          * <li>Some other thread {@link Thread#interrupt interrupts}
760          * the current thread; or
761          *
762          * <li>The specified waiting time elapses
763          *
764          * </ul>
765          *
766          * <p>If the write lock is acquired then the value <tt>true</tt> is
767          * returned and the write lock hold count is set to one.
768          *
769          * <p>If the current thread:
770          *
771          * <ul>
772          *
773          * <li>has its interrupted status set on entry to this method;
774          * or
775          *
776          * <li>is {@link Thread#interrupt interrupted} while acquiring
777          * the write lock,
778          *
779          * </ul>
780          *
781          * then {@link InterruptedException} is thrown and the current
782          * thread's interrupted status is cleared.
783          *
784          * <p>If the specified waiting time elapses then the value
785          * <tt>false</tt> is returned. If the time is less than or
786          * equal to zero, the method will not wait at all.
787          *
788          * <p>In this implementation, as this method is an explicit
789          * interruption point, preference is given to responding to
790          * the interrupt over normal or reentrant acquisition of the
791          * lock, and over reporting the elapse of the waiting time.
792          *
793          * @param timeout the time to wait for the write lock
794          * @param unit the time unit of the timeout argument
795          *
796          * @return <tt>true</tt> if the lock was free and was acquired
797          * by the current thread, or the write lock was already held by the
798          * current thread; and <tt>false</tt> if the waiting time
799          * elapsed before the lock could be acquired.
800          *
801          * @throws InterruptedException if the current thread is interrupted
802          * @throws NullPointerException if unit is null
803          *
804          */

805         public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException JavaDoc {
806             return sync.tryAcquireNanos(1, unit.toNanos(timeout));
807         }
808         
809         /**
810          * Attempts to release this lock.
811          *
812          * <p>If the current thread is the holder of this lock then
813          * the hold count is decremented. If the hold count is now
814          * zero then the lock is released. If the current thread is
815          * not the holder of this lock then {@link
816          * IllegalMonitorStateException} is thrown.
817          * @throws IllegalMonitorStateException if the current thread does not
818          * hold this lock.
819          */

820         public void unlock() {
821             sync.release(1);
822         }
823
824         /**
825          * Returns a {@link Condition} instance for use with this
826          * {@link Lock} instance.
827          * <p>The returned {@link Condition} instance supports the same
828          * usages as do the {@link Object} monitor methods ({@link
829          * Object#wait() wait}, {@link Object#notify notify}, and {@link
830          * Object#notifyAll notifyAll}) when used with the built-in
831          * monitor lock.
832          *
833          * <ul>
834          *
835          * <li>If this write lock is not held when any {@link
836          * Condition} method is called then an {@link
837          * IllegalMonitorStateException} is thrown. (Read locks are
838          * held independently of write locks, so are not checked or
839          * affected. However it is essentially always an error to
840          * invoke a condition waiting method when the current thread
841          * has also acquired read locks, since other threads that
842          * could unblock it will not be able to acquire the write
843          * lock.)
844          *
845          * <li>When the condition {@link Condition#await() waiting}
846          * methods are called the write lock is released and, before
847          * they return, the write lock is reacquired and the lock hold
848          * count restored to what it was when the method was called.
849          *
850          * <li>If a thread is {@link Thread#interrupt interrupted} while
851          * waiting then the wait will terminate, an {@link
852          * InterruptedException} will be thrown, and the thread's
853          * interrupted status will be cleared.
854          *
855          * <li> Waiting threads are signalled in FIFO order.
856          *
857          * <li>The ordering of lock reacquisition for threads returning
858          * from waiting methods is the same as for threads initially
859          * acquiring the lock, which is in the default case not specified,
860          * but for <em>fair</em> locks favors those threads that have been
861          * waiting the longest.
862          *
863          * </ul>
864          * @return the Condition object
865          */

866         public Condition JavaDoc newCondition() {
867             return sync.newCondition();
868         }
869
870         /**
871          * Returns a string identifying this lock, as well as its lock
872          * state. The state, in brackets includes either the String
873          * &quot;Unlocked&quot; or the String &quot;Locked by&quot;
874          * followed by the {@link Thread#getName} of the owning thread.
875          * @return a string identifying this lock, as well as its lock state.
876          */

877         public String JavaDoc toString() {
878             Thread JavaDoc owner = sync.getOwner();
879             return super.toString() + ((owner == null) ?
880                                        "[Unlocked]" :
881                                        "[Locked by thread " + owner.getName() + "]");
882         }
883
884     }
885
886
887     // Instrumentation and status
888

889     /**
890      * Returns true if this lock has fairness set true.
891      * @return true if this lock has fairness set true.
892      */

893     public final boolean isFair() {
894         return sync instanceof FairSync;
895     }
896
897     /**
898      * Returns the thread that currently owns the write lock, or
899      * <tt>null</tt> if not owned. Note that the owner may be
900      * momentarily <tt>null</tt> even if there are threads trying to
901      * acquire the lock but have not yet done so. This method is
902      * designed to facilitate construction of subclasses that provide
903      * more extensive lock monitoring facilities.
904      * @return the owner, or <tt>null</tt> if not owned.
905      */

906     protected Thread JavaDoc getOwner() {
907         return sync.getOwner();
908     }
909     
910     /**
911      * Queries the number of read locks held for this lock. This
912      * method is designed for use in monitoring system state, not for
913      * synchronization control.
914      * @return the number of read locks held.
915      */

916     public int getReadLockCount() {
917         return sync.getReadLockCount();
918     }
919
920     /**
921      * Queries if the write lock is held by any thread. This method is
922      * designed for use in monitoring system state, not for
923      * synchronization control.
924      * @return <tt>true</tt> if any thread holds the write lock and
925      * <tt>false</tt> otherwise.
926      */

927     public boolean isWriteLocked() {
928         return sync.isWriteLocked();
929     }
930
931     /**
932      * Queries if the write lock is held by the current thread.
933      * @return <tt>true</tt> if the current thread holds the write lock and
934      * <tt>false</tt> otherwise.
935      */

936     public boolean isWriteLockedByCurrentThread() {
937         return sync.isHeldExclusively();
938     }
939
940     /**
941      * Queries the number of reentrant write holds on this lock by the
942      * current thread. A writer thread has a hold on a lock for
943      * each lock action that is not matched by an unlock action.
944      *
945      * @return the number of holds on the write lock by the current thread,
946      * or zero if the write lock is not held by the current thread.
947      */

948     public int getWriteHoldCount() {
949         return sync.getWriteHoldCount();
950     }
951
952     /**
953      * Returns a collection containing threads that may be waiting to
954      * acquire the write lock. Because the actual set of threads may
955      * change dynamically while constructing this result, the returned
956      * collection is only a best-effort estimate. The elements of the
957      * returned collection are in no particular order. This method is
958      * designed to facilitate construction of subclasses that provide
959      * more extensive lock monitoring facilities.
960      * @return the collection of threads
961      */

962     protected Collection<Thread JavaDoc> getQueuedWriterThreads() {
963         return sync.getExclusiveQueuedThreads();
964     }
965
966     /**
967      * Returns a collection containing threads that may be waiting to
968      * acquire the read lock. Because the actual set of threads may
969      * change dynamically while constructing this result, the returned
970      * collection is only a best-effort estimate. The elements of the
971      * returned collection are in no particular order. This method is
972      * designed to facilitate construction of subclasses that provide
973      * more extensive lock monitoring facilities.
974      * @return the collection of threads
975      */

976     protected Collection<Thread JavaDoc> getQueuedReaderThreads() {
977         return sync.getSharedQueuedThreads();
978     }
979
980     /**
981      * Queries whether any threads are waiting to acquire the read or
982      * write lock. Note that because cancellations may occur at any
983      * time, a <tt>true</tt> return does not guarantee that any other
984      * thread will ever acquire a lock. This method is designed
985      * primarily for use in monitoring of the system state.
986      *
987      * @return true if there may be other threads waiting to acquire
988      * the lock.
989      */

990     public final boolean hasQueuedThreads() {
991         return sync.hasQueuedThreads();
992     }
993
994     /**
995      * Queries whether the given thread is waiting to acquire either
996      * the read or write lock. Note that because cancellations may
997      * occur at any time, a <tt>true</tt> return does not guarantee
998      * that this thread will ever acquire a lock. This method is
999      * designed primarily for use in monitoring of the system state.
1000     *
1001     * @param thread the thread
1002     * @return true if the given thread is queued waiting for this lock.
1003     * @throws NullPointerException if thread is null
1004     */

1005    public final boolean hasQueuedThread(Thread JavaDoc thread) {
1006        return sync.isQueued(thread);
1007    }
1008
1009    /**
1010     * Returns an estimate of the number of threads waiting to acquire
1011     * either the read or write lock. The value is only an estimate
1012     * because the number of threads may change dynamically while this
1013     * method traverses internal data structures. This method is
1014     * designed for use in monitoring of the system state, not for
1015     * synchronization control.
1016     * @return the estimated number of threads waiting for this lock
1017     */

1018    public final int getQueueLength() {
1019        return sync.getQueueLength();
1020    }
1021
1022    /**
1023     * Returns a collection containing threads that may be waiting to
1024     * acquire either the read or write lock. Because the actual set
1025     * of threads may change dynamically while constructing this
1026     * result, the returned collection is only a best-effort estimate.
1027     * The elements of the returned collection are in no particular
1028     * order. This method is designed to facilitate construction of
1029     * subclasses that provide more extensive monitoring facilities.
1030     * @return the collection of threads
1031     */

1032    protected Collection<Thread JavaDoc> getQueuedThreads() {
1033        return sync.getQueuedThreads();
1034    }
1035
1036    /**
1037     * Queries whether any threads are waiting on the given condition
1038     * associated with the write lock. Note that because timeouts and
1039     * interrupts may occur at any time, a <tt>true</tt> return does
1040     * not guarantee that a future <tt>signal</tt> will awaken any
1041     * threads. This method is designed primarily for use in
1042     * monitoring of the system state.
1043     * @param condition the condition
1044     * @return <tt>true</tt> if there are any waiting threads.
1045     * @throws IllegalMonitorStateException if this lock
1046     * is not held
1047     * @throws IllegalArgumentException if the given condition is
1048     * not associated with this lock
1049     * @throws NullPointerException if condition null
1050     */

1051    public boolean hasWaiters(Condition JavaDoc condition) {
1052        if (condition == null)
1053            throw new NullPointerException JavaDoc();
1054        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject JavaDoc))
1055            throw new IllegalArgumentException JavaDoc("not owner");
1056        return sync.hasWaiters((AbstractQueuedSynchronizer.ConditionObject JavaDoc)condition);
1057    }
1058
1059    /**
1060     * Returns an estimate of the number of threads waiting on the
1061     * given condition associated with the write lock. Note that because
1062     * timeouts and interrupts may occur at any time, the estimate
1063     * serves only as an upper bound on the actual number of waiters.
1064     * This method is designed for use in monitoring of the system
1065     * state, not for synchronization control.
1066     * @param condition the condition
1067     * @return the estimated number of waiting threads.
1068     * @throws IllegalMonitorStateException if this lock
1069     * is not held
1070     * @throws IllegalArgumentException if the given condition is
1071     * not associated with this lock
1072     * @throws NullPointerException if condition null
1073     */

1074    public int getWaitQueueLength(Condition JavaDoc condition) {
1075        if (condition == null)
1076            throw new NullPointerException JavaDoc();
1077        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject JavaDoc))
1078            throw new IllegalArgumentException JavaDoc("not owner");
1079        return sync.getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject JavaDoc)condition);
1080    }
1081
1082    /**
1083     * Returns a collection containing those threads that may be
1084     * waiting on the given condition associated with the write lock.
1085     * Because the actual set of threads may change dynamically while
1086     * constructing this result, the returned collection is only a
1087     * best-effort estimate. The elements of the returned collection
1088     * are in no particular order. This method is designed to
1089     * facilitate construction of subclasses that provide more
1090     * extensive condition monitoring facilities.
1091     * @param condition the condition
1092     * @return the collection of threads
1093     * @throws IllegalMonitorStateException if this lock
1094     * is not held
1095     * @throws IllegalArgumentException if the given condition is
1096     * not associated with this lock
1097     * @throws NullPointerException if condition null
1098     */

1099    protected Collection<Thread JavaDoc> getWaitingThreads(Condition JavaDoc condition) {
1100        if (condition == null)
1101            throw new NullPointerException JavaDoc();
1102        if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject JavaDoc))
1103            throw new IllegalArgumentException JavaDoc("not owner");
1104        return sync.getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject JavaDoc)condition);
1105    }
1106
1107    /**
1108     * Returns a string identifying this lock, as well as its lock state.
1109     * The state, in brackets, includes the String &quot;Write locks =&quot;
1110     * followed by the number of reentrantly held write locks, and the
1111     * String &quot;Read locks =&quot; followed by the number of held
1112     * read locks.
1113     * @return a string identifying this lock, as well as its lock state.
1114     */

1115    public String JavaDoc toString() {
1116        int c = sync.getCount();
1117        int w = exclusiveCount(c);
1118        int r = sharedCount(c);
1119        
1120        return super.toString() +
1121            "[Write locks = " + w + ", Read locks = " + r + "]";
1122    }
1123
1124}
1125
Popular Tags