0001: /*
0002: * Written by Doug Lea with assistance from members of JCP JSR-166
0003: * Expert Group and released to the public domain, as explained at
0004: * http://creativecommons.org/licenses/publicdomain
0005: */
0006:
0007: package java.util.concurrent.locks;
0008:
0009: import java.util.concurrent.*;
0010: import java.util.concurrent.atomic.*;
0011: import java.util.*;
0012:
0013: /**
0014: * An implementation of {@link ReadWriteLock} supporting similar
0015: * semantics to {@link ReentrantLock}.
0016: * <p>This class has the following properties:
0017: *
0018: * <ul>
0019: * <li><b>Acquisition order</b>
0020: *
0021: * <p> This class does not impose a reader or writer preference
0022: * ordering for lock access. However, it does support an optional
0023: * <em>fairness</em> policy. When constructed as fair, threads
0024: * contend for entry using an approximately arrival-order policy. When
0025: * the write lock is released either the longest-waiting single writer
0026: * will be assigned the write lock, or if there is a reader waiting
0027: * longer than any writer, the set of readers will be assigned the
0028: * read lock. When constructed as non-fair, the order of entry to the
0029: * lock need not be in arrival order. In either case, if readers are
0030: * active and a writer enters the lock then no subsequent readers will
0031: * be granted the read lock until after that writer has acquired and
0032: * released the write lock.
0033: *
0034: * <li><b>Reentrancy</b>
0035: * <p>This lock allows both readers and writers to reacquire read or
0036: * write locks in the style of a {@link ReentrantLock}. Readers are not
0037: * allowed until all write locks held by the writing thread have been
0038: * released.
0039: * <p>Additionally, a writer can acquire the read lock - but not vice-versa.
0040: * Among other applications, reentrancy can be useful when
0041: * write locks are held during calls or callbacks to methods that
0042: * perform reads under read locks.
0043: * If a reader tries to acquire the write lock it will never succeed.
0044: *
0045: * <li><b>Lock downgrading</b>
0046: * <p>Reentrancy also allows downgrading from the write lock to a read lock,
0047: * by acquiring the write lock, then the read lock and then releasing the
0048: * write lock. However, upgrading from a read lock to the write lock, is
0049: * <b>not</b> possible.
0050: *
0051: * <li><b>Interruption of lock acquisition</b>
0052: * <p>The read lock and write lock both support interruption during lock
0053: * acquisition.
0054: *
0055: * <li><b>{@link Condition} support</b>
0056: * <p>The write lock provides a {@link Condition} implementation that
0057: * behaves in the same way, with respect to the write lock, as the
0058: * {@link Condition} implementation provided by
0059: * {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
0060: * This {@link Condition} can, of course, only be used with the write lock.
0061: * <p>The read lock does not support a {@link Condition} and
0062: * <tt>readLock().newCondition()</tt> throws
0063: * <tt>UnsupportedOperationException</tt>.
0064: *
0065: * <li><b>Instrumentation</b>
0066: * <P> This class supports methods to determine whether locks
0067: * are held or contended. These methods are designed for monitoring
0068: * system state, not for synchronization control.
0069: * </ul>
0070: *
0071: * <p> Serialization of this class behaves in the same way as built-in
0072: * locks: a deserialized lock is in the unlocked state, regardless of
0073: * its state when serialized.
0074: *
0075: * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
0076: * reentrancy to perform lock downgrading after updating a cache (exception
0077: * handling is elided for simplicity):
0078: * <pre>
0079: * class CachedData {
0080: * Object data;
0081: * volatile boolean cacheValid;
0082: * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
0083: *
0084: * void processCachedData() {
0085: * rwl.readLock().lock();
0086: * if (!cacheValid) {
0087: * // upgrade lock manually
0088: * rwl.readLock().unlock(); // must unlock first to obtain writelock
0089: * rwl.writeLock().lock();
0090: * if (!cacheValid) { // recheck
0091: * data = ...
0092: * cacheValid = true;
0093: * }
0094: * // downgrade lock
0095: * rwl.readLock().lock(); // reacquire read without giving up write lock
0096: * rwl.writeLock().unlock(); // unlock write, still hold read
0097: * }
0098: *
0099: * use(data);
0100: * rwl.readLock().unlock();
0101: * }
0102: * }
0103: * </pre>
0104: *
0105: * ReentrantReadWriteLocks can be used to improve concurrency in some
0106: * uses of some kinds of Collections. This is typically worthwhile
0107: * only when the collections are expected to be large, accessed by
0108: * more reader threads than writer threads, and entail operations with
0109: * overhead that outweighs synchronization overhead. For example, here
0110: * is a class using a TreeMap that is expected to be large and
0111: * concurrently accessed.
0112: *
0113: * <pre>
0114: * class RWDictionary {
0115: * private final Map<String, Data> m = new TreeMap<String, Data>();
0116: * private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
0117: * private final Lock r = rwl.readLock();
0118: * private final Lock w = rwl.writeLock();
0119: *
0120: * public Data get(String key) {
0121: * r.lock(); try { return m.get(key); } finally { r.unlock(); }
0122: * }
0123: * public String[] allKeys() {
0124: * r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }
0125: * }
0126: * public Data put(String key, Data value) {
0127: * w.lock(); try { return m.put(key, value); } finally { w.unlock(); }
0128: * }
0129: * public void clear() {
0130: * w.lock(); try { m.clear(); } finally { w.unlock(); }
0131: * }
0132: * }
0133: * </pre>
0134: *
0135: *
0136: * <h3>Implementation Notes</h3>
0137: *
0138: * <p>A reentrant write lock intrinsically defines an owner and can
0139: * only be released by the thread that acquired it. In contrast, in
0140: * this implementation, the read lock has no concept of ownership, and
0141: * there is no requirement that the thread releasing a read lock is
0142: * the same as the one that acquired it. However, this property is
0143: * not guaranteed to hold in future implementations of this class.
0144: *
0145: * <p> This lock supports a maximum of 65536 recursive write locks
0146: * and 65536 read locks. Attempts to exceed these limits result in
0147: * {@link Error} throws from locking methods.
0148: *
0149: * @since 1.5
0150: * @author Doug Lea
0151: *
0152: */
0153: public class ReentrantReadWriteLock implements ReadWriteLock,
0154: java.io.Serializable {
0155: private static final long serialVersionUID = -6992448646407690164L;
0156: /** Inner class providing readlock */
0157: private final ReentrantReadWriteLock.ReadLock readerLock;
0158: /** Inner class providing writelock */
0159: private final ReentrantReadWriteLock.WriteLock writerLock;
0160: /** Performs all synchronization mechanics */
0161: private final Sync sync;
0162:
0163: /**
0164: * Creates a new <tt>ReentrantReadWriteLock</tt> with
0165: * default ordering properties.
0166: */
0167: public ReentrantReadWriteLock() {
0168: sync = new NonfairSync();
0169: readerLock = new ReadLock(this );
0170: writerLock = new WriteLock(this );
0171: }
0172:
0173: /**
0174: * Creates a new <tt>ReentrantReadWriteLock</tt> with
0175: * the given fairness policy.
0176: *
0177: * @param fair true if this lock should use a fair ordering policy
0178: */
0179: public ReentrantReadWriteLock(boolean fair) {
0180: sync = (fair) ? new FairSync() : new NonfairSync();
0181: readerLock = new ReadLock(this );
0182: writerLock = new WriteLock(this );
0183: }
0184:
0185: public ReentrantReadWriteLock.WriteLock writeLock() {
0186: return writerLock;
0187: }
0188:
0189: public ReentrantReadWriteLock.ReadLock readLock() {
0190: return readerLock;
0191: }
0192:
0193: /*
0194: * Read vs write count extraction constants and functions.
0195: * Lock state is logically divided into two shorts: The lower
0196: * one representing the exclusive (writer) lock hold count,
0197: * and the upper the shared (reader) hold count.
0198: */
0199:
0200: static final int SHARED_SHIFT = 16;
0201: static final int SHARED_UNIT = (1 << SHARED_SHIFT);
0202: static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
0203:
0204: /** Returns the number of shared holds represented in count */
0205: static int sharedCount(int c) {
0206: return c >>> SHARED_SHIFT;
0207: }
0208:
0209: /** Returns the number of exclusive holds represented in count */
0210: static int exclusiveCount(int c) {
0211: return c & EXCLUSIVE_MASK;
0212: }
0213:
0214: /**
0215: * Synchronization implementation for ReentrantReadWriteLock.
0216: * Subclassed into fair and nonfair versions.
0217: */
0218: abstract static class Sync extends AbstractQueuedSynchronizer {
0219: /** Current (exclusive) owner thread */
0220: transient Thread owner;
0221:
0222: /**
0223: * Perform write lock. Allows fast path in non-fair version.
0224: */
0225: abstract void wlock();
0226:
0227: /**
0228: * Perform non-fair tryLock for write. tryAcquire is
0229: * implemented in subclasses, but both versions need nonfair
0230: * try for trylock method
0231: */
0232: final boolean nonfairTryAcquire(int acquires) {
0233: // mask out readlocks if called from condition methods
0234: acquires = exclusiveCount(acquires);
0235: Thread current = Thread.currentThread();
0236: int c = getState();
0237: int w = exclusiveCount(c);
0238: if (w + acquires >= SHARED_UNIT)
0239: throw new Error("Maximum lock count exceeded");
0240: if (c != 0 && (w == 0 || current != owner))
0241: return false;
0242: if (!compareAndSetState(c, c + acquires))
0243: return false;
0244: owner = current;
0245: return true;
0246: }
0247:
0248: /**
0249: * Perform nonfair tryLock for read.
0250: */
0251: final int nonfairTryAcquireShared(int acquires) {
0252: for (;;) {
0253: int c = getState();
0254: int nextc = c + (acquires << SHARED_SHIFT);
0255: if (nextc < c)
0256: throw new Error("Maximum lock count exceeded");
0257: if (exclusiveCount(c) != 0
0258: && owner != Thread.currentThread())
0259: return -1;
0260: if (compareAndSetState(c, nextc))
0261: return 1;
0262: // Recheck count if lost CAS
0263: }
0264: }
0265:
0266: protected final boolean tryRelease(int releases) {
0267: Thread current = Thread.currentThread();
0268: int c = getState();
0269: if (owner != current)
0270: throw new IllegalMonitorStateException();
0271: int nextc = c - releases;
0272: boolean free = false;
0273: if (exclusiveCount(c) == releases) {
0274: free = true;
0275: owner = null;
0276: }
0277: setState(nextc);
0278: return free;
0279: }
0280:
0281: protected final boolean tryReleaseShared(int releases) {
0282: for (;;) {
0283: int c = getState();
0284: int nextc = c - (releases << SHARED_SHIFT);
0285: if (nextc < 0)
0286: throw new IllegalMonitorStateException();
0287: if (compareAndSetState(c, nextc))
0288: return nextc == 0;
0289: }
0290: }
0291:
0292: protected final boolean isHeldExclusively() {
0293: return exclusiveCount(getState()) != 0
0294: && owner == Thread.currentThread();
0295: }
0296:
0297: // Methods relayed to outer class
0298:
0299: final ConditionObject newCondition() {
0300: return new ConditionObject();
0301: }
0302:
0303: final Thread getOwner() {
0304: int c = exclusiveCount(getState());
0305: Thread o = owner;
0306: return (c == 0) ? null : o;
0307: }
0308:
0309: final int getReadLockCount() {
0310: return sharedCount(getState());
0311: }
0312:
0313: final boolean isWriteLocked() {
0314: return exclusiveCount(getState()) != 0;
0315: }
0316:
0317: final int getWriteHoldCount() {
0318: int c = exclusiveCount(getState());
0319: Thread o = owner;
0320: return (o == Thread.currentThread()) ? c : 0;
0321: }
0322:
0323: /**
0324: * Reconstitute this lock instance from a stream
0325: * @param s the stream
0326: */
0327: private void readObject(java.io.ObjectInputStream s)
0328: throws java.io.IOException, ClassNotFoundException {
0329: s.defaultReadObject();
0330: setState(0); // reset to unlocked state
0331: }
0332:
0333: final int getCount() {
0334: return getState();
0335: }
0336: }
0337:
0338: /**
0339: * Nonfair version of Sync
0340: */
0341: final static class NonfairSync extends Sync {
0342: protected final boolean tryAcquire(int acquires) {
0343: return nonfairTryAcquire(acquires);
0344: }
0345:
0346: protected final int tryAcquireShared(int acquires) {
0347: return nonfairTryAcquireShared(acquires);
0348: }
0349:
0350: // Use fastpath for main write lock method
0351: final void wlock() {
0352: if (compareAndSetState(0, 1))
0353: owner = Thread.currentThread();
0354: else
0355: acquire(1);
0356: }
0357: }
0358:
0359: /**
0360: * Fair version of Sync
0361: */
0362: final static class FairSync extends Sync {
0363: protected final boolean tryAcquire(int acquires) {
0364: // mask out readlocks if called from condition methods
0365: acquires = exclusiveCount(acquires);
0366: Thread current = Thread.currentThread();
0367: Thread first;
0368: int c = getState();
0369: int w = exclusiveCount(c);
0370: if (w + acquires >= SHARED_UNIT)
0371: throw new Error("Maximum lock count exceeded");
0372: if ((w == 0 || current != owner)
0373: && (c != 0 || ((first = getFirstQueuedThread()) != null && first != current)))
0374: return false;
0375: if (!compareAndSetState(c, c + acquires))
0376: return false;
0377: owner = current;
0378: return true;
0379: }
0380:
0381: protected final int tryAcquireShared(int acquires) {
0382: Thread current = Thread.currentThread();
0383: for (;;) {
0384: Thread first = getFirstQueuedThread();
0385: if (first != null && first != current)
0386: return -1;
0387: int c = getState();
0388: int nextc = c + (acquires << SHARED_SHIFT);
0389: if (nextc < c)
0390: throw new Error("Maximum lock count exceeded");
0391: if (exclusiveCount(c) != 0
0392: && owner != Thread.currentThread())
0393: return -1;
0394: if (compareAndSetState(c, nextc))
0395: return 1;
0396: // Recheck count if lost CAS
0397: }
0398: }
0399:
0400: final void wlock() { // no fast path
0401: acquire(1);
0402: }
0403: }
0404:
0405: /**
0406: * The lock returned by method {@link ReentrantReadWriteLock#readLock}.
0407: */
0408: public static class ReadLock implements Lock, java.io.Serializable {
0409: private static final long serialVersionUID = -5992448646407690164L;
0410: private final Sync sync;
0411:
0412: /**
0413: * Constructor for use by subclasses
0414: * @param lock the outer lock object
0415: * @throws NullPointerException if lock null
0416: */
0417: protected ReadLock(ReentrantReadWriteLock lock) {
0418: sync = lock.sync;
0419: }
0420:
0421: /**
0422: * Acquires the shared lock.
0423: *
0424: * <p>Acquires the lock if it is not held exclusively by
0425: * another thread and returns immediately.
0426: *
0427: * <p>If the lock is held exclusively by another thread then
0428: * the current thread becomes disabled for thread scheduling
0429: * purposes and lies dormant until the lock has been acquired.
0430: */
0431: public void lock() {
0432: sync.acquireShared(1);
0433: }
0434:
0435: /**
0436: * Acquires the shared lock unless the current thread is
0437: * {@link Thread#interrupt interrupted}.
0438: *
0439: * <p>Acquires the shared lock if it is not held exclusively
0440: * by another thread and returns immediately.
0441: *
0442: * <p>If the lock is held by another thread then the
0443: * current thread becomes disabled for thread scheduling
0444: * purposes and lies dormant until one of two things happens:
0445: *
0446: * <ul>
0447: *
0448: * <li>The lock is acquired by the current thread; or
0449: *
0450: * <li>Some other thread {@link Thread#interrupt interrupts}
0451: * the current thread.
0452: *
0453: * </ul>
0454: *
0455: * <p>If the current thread:
0456: *
0457: * <ul>
0458: *
0459: * <li>has its interrupted status set on entry to this method; or
0460: *
0461: * <li>is {@link Thread#interrupt interrupted} while acquiring
0462: * the lock,
0463: *
0464: * </ul>
0465: *
0466: * then {@link InterruptedException} is thrown and the current
0467: * thread's interrupted status is cleared.
0468: *
0469: * <p>In this implementation, as this method is an explicit
0470: * interruption point, preference is given to responding to
0471: * the interrupt over normal or reentrant acquisition of the
0472: * lock.
0473: *
0474: * @throws InterruptedException if the current thread is interrupted
0475: */
0476: public void lockInterruptibly() throws InterruptedException {
0477: sync.acquireSharedInterruptibly(1);
0478: }
0479:
0480: /**
0481: * Acquires the shared lock only if it is not held exclusively by
0482: * another thread at the time of invocation.
0483: *
0484: * <p>Acquires the lock if it is not held exclusively by
0485: * another thread and returns immediately with the value
0486: * <tt>true</tt>. Even when this lock has been set to use a
0487: * fair ordering policy, a call to <tt>tryLock()</tt>
0488: * <em>will</em> immediately acquire the lock if it is
0489: * available, whether or not other threads are currently
0490: * waiting for the lock. This "barging" behavior
0491: * can be useful in certain circumstances, even though it
0492: * breaks fairness. If you want to honor the fairness setting
0493: * for this lock, then use {@link #tryLock(long, TimeUnit)
0494: * tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
0495: * (it also detects interruption).
0496: *
0497: * <p>If the lock is held exclusively by another thread then
0498: * this method will return immediately with the value
0499: * <tt>false</tt>.
0500: *
0501: * @return <tt>true</tt> if the lock was acquired.
0502: */
0503: public boolean tryLock() {
0504: return sync.nonfairTryAcquireShared(1) >= 0;
0505: }
0506:
0507: /**
0508: * Acquires the shared lock if it is not held exclusively by
0509: * another thread within the given waiting time and the
0510: * current thread has not been {@link Thread#interrupt
0511: * interrupted}.
0512: *
0513: * <p>Acquires the lock if it is not held exclusively by
0514: * another thread and returns immediately with the value
0515: * <tt>true</tt>. If this lock has been set to use a fair
0516: * ordering policy then an available lock <em>will not</em> be
0517: * acquired if any other threads are waiting for the
0518: * lock. This is in contrast to the {@link #tryLock()}
0519: * method. If you want a timed <tt>tryLock</tt> that does
0520: * permit barging on a fair lock then combine the timed and
0521: * un-timed forms together:
0522: *
0523: * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
0524: * </pre>
0525: *
0526: * <p>If the lock is held exclusively by another thread then the
0527: * current thread becomes disabled for thread scheduling
0528: * purposes and lies dormant until one of three things happens:
0529: *
0530: * <ul>
0531: *
0532: * <li>The lock is acquired by the current thread; or
0533: *
0534: * <li>Some other thread {@link Thread#interrupt interrupts} the current
0535: * thread; or
0536: *
0537: * <li>The specified waiting time elapses
0538: *
0539: * </ul>
0540: *
0541: * <p>If the lock is acquired then the value <tt>true</tt> is
0542: * returned.
0543: *
0544: * <p>If the current thread:
0545: *
0546: * <ul>
0547: *
0548: * <li>has its interrupted status set on entry to this method; or
0549: *
0550: * <li>is {@link Thread#interrupt interrupted} while acquiring
0551: * the lock,
0552: *
0553: * </ul> then {@link InterruptedException} is thrown and the
0554: * current thread's interrupted status is cleared.
0555: *
0556: * <p>If the specified waiting time elapses then the value
0557: * <tt>false</tt> is returned. If the time is less than or
0558: * equal to zero, the method will not wait at all.
0559: *
0560: * <p>In this implementation, as this method is an explicit
0561: * interruption point, preference is given to responding to
0562: * the interrupt over normal or reentrant acquisition of the
0563: * lock, and over reporting the elapse of the waiting time.
0564: *
0565: * @param timeout the time to wait for the lock
0566: * @param unit the time unit of the timeout argument
0567: *
0568: * @return <tt>true</tt> if the lock was acquired.
0569: *
0570: * @throws InterruptedException if the current thread is interrupted
0571: * @throws NullPointerException if unit is null
0572: *
0573: */
0574: public boolean tryLock(long timeout, TimeUnit unit)
0575: throws InterruptedException {
0576: return sync.tryAcquireSharedNanos(1, unit.toNanos(timeout));
0577: }
0578:
0579: /**
0580: * Attempts to release this lock.
0581: *
0582: * <p> If the number of readers is now zero then the lock
0583: * is made available for other lock attempts.
0584: */
0585: public void unlock() {
0586: sync.releaseShared(1);
0587: }
0588:
0589: /**
0590: * Throws UnsupportedOperationException because ReadLocks
0591: * do not support conditions.
0592: * @throws UnsupportedOperationException always
0593: */
0594: public Condition newCondition() {
0595: throw new UnsupportedOperationException();
0596: }
0597:
0598: /**
0599: * Returns a string identifying this lock, as well as its lock state.
0600: * The state, in brackets, includes the String
0601: * "Read locks =" followed by the number of held
0602: * read locks.
0603: * @return a string identifying this lock, as well as its lock state.
0604: */
0605: public String toString() {
0606: int r = sync.getReadLockCount();
0607: return super .toString() + "[Read locks = " + r + "]";
0608: }
0609:
0610: }
0611:
0612: /**
0613: * The lock returned by method {@link ReentrantReadWriteLock#writeLock}.
0614: */
0615: public static class WriteLock implements Lock, java.io.Serializable {
0616: private static final long serialVersionUID = -4992448646407690164L;
0617: private final Sync sync;
0618:
0619: /**
0620: * Constructor for use by subclasses
0621: * @param lock the outer lock object
0622: * @throws NullPointerException if lock null
0623: */
0624: protected WriteLock(ReentrantReadWriteLock lock) {
0625: sync = lock.sync;
0626: }
0627:
0628: /**
0629: * Acquire the lock.
0630: *
0631: * <p>Acquires the lock if it is not held by another thread
0632: * and returns immediately, setting the lock hold count to
0633: * one.
0634: *
0635: * <p>If the current thread already holds the lock then the
0636: * hold count is incremented by one and the method returns
0637: * immediately.
0638: *
0639: * <p>If the lock is held by another thread then the current
0640: * thread becomes disabled for thread scheduling purposes and
0641: * lies dormant until the lock has been acquired, at which
0642: * time the lock hold count is set to one.
0643: */
0644: public void lock() {
0645: sync.wlock();
0646: }
0647:
0648: /**
0649: * Acquires the lock unless the current thread is {@link
0650: * Thread#interrupt interrupted}.
0651: *
0652: * <p>Acquires the lock if it is not held by another thread
0653: * and returns immediately, setting the lock hold count to
0654: * one.
0655: *
0656: * <p>If the current thread already holds this lock then the
0657: * hold count is incremented by one and the method returns
0658: * immediately.
0659: *
0660: * <p>If the lock is held by another thread then the current
0661: * thread becomes disabled for thread scheduling purposes and
0662: * lies dormant until one of two things happens:
0663: *
0664: * <ul>
0665: *
0666: * <li>The lock is acquired by the current thread; or
0667: *
0668: * <li>Some other thread {@link Thread#interrupt interrupts}
0669: * the current thread.
0670: *
0671: * </ul>
0672: *
0673: * <p>If the lock is acquired by the current thread then the
0674: * lock hold count is set to one.
0675: *
0676: * <p>If the current thread:
0677: *
0678: * <ul>
0679: *
0680: * <li>has its interrupted status set on entry to this method;
0681: * or
0682: *
0683: * <li>is {@link Thread#interrupt interrupted} while acquiring
0684: * the lock,
0685: *
0686: * </ul>
0687: *
0688: * then {@link InterruptedException} is thrown and the current
0689: * thread's interrupted status is cleared.
0690: *
0691: * <p>In this implementation, as this method is an explicit
0692: * interruption point, preference is given to responding to
0693: * the interrupt over normal or reentrant acquisition of the
0694: * lock.
0695: *
0696: * @throws InterruptedException if the current thread is interrupted
0697: */
0698: public void lockInterruptibly() throws InterruptedException {
0699: sync.acquireInterruptibly(1);
0700: }
0701:
0702: /**
0703: * Acquires the lock only if it is not held by another thread
0704: * at the time of invocation.
0705: *
0706: * <p>Acquires the lock if it is not held by another thread
0707: * and returns immediately with the value <tt>true</tt>,
0708: * setting the lock hold count to one. Even when this lock has
0709: * been set to use a fair ordering policy, a call to
0710: * <tt>tryLock()</tt> <em>will</em> immediately acquire the
0711: * lock if it is available, whether or not other threads are
0712: * currently waiting for the lock. This "barging"
0713: * behavior can be useful in certain circumstances, even
0714: * though it breaks fairness. If you want to honor the
0715: * fairness setting for this lock, then use {@link
0716: * #tryLock(long, TimeUnit) tryLock(0, TimeUnit.SECONDS) }
0717: * which is almost equivalent (it also detects interruption).
0718: *
0719: * <p> If the current thread already holds this lock then the
0720: * hold count is incremented by one and the method returns
0721: * <tt>true</tt>.
0722: *
0723: * <p>If the lock is held by another thread then this method
0724: * will return immediately with the value <tt>false</tt>.
0725: *
0726: * @return <tt>true</tt> if the lock was free and was acquired by the
0727: * current thread, or the lock was already held by the current thread; and
0728: * <tt>false</tt> otherwise.
0729: */
0730: public boolean tryLock() {
0731: return sync.nonfairTryAcquire(1);
0732: }
0733:
0734: /**
0735: * Acquires the lock if it is not held by another thread
0736: * within the given waiting time and the current thread has
0737: * not been {@link Thread#interrupt interrupted}.
0738: *
0739: * <p>Acquires the lock if it is not held by another thread
0740: * and returns immediately with the value <tt>true</tt>,
0741: * setting the lock hold count to one. If this lock has been
0742: * set to use a fair ordering policy then an available lock
0743: * <em>will not</em> be acquired if any other threads are
0744: * waiting for the lock. This is in contrast to the {@link
0745: * #tryLock()} method. If you want a timed <tt>tryLock</tt>
0746: * that does permit barging on a fair lock then combine the
0747: * timed and un-timed forms together:
0748: *
0749: * <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
0750: * </pre>
0751: *
0752: * <p>If the current thread already holds this lock then the
0753: * hold count is incremented by one and the method returns
0754: * <tt>true</tt>.
0755: *
0756: * <p>If the lock is held by another thread then the current
0757: * thread becomes disabled for thread scheduling purposes and
0758: * lies dormant until one of three things happens:
0759: *
0760: * <ul>
0761: *
0762: * <li>The lock is acquired by the current thread; or
0763: *
0764: * <li>Some other thread {@link Thread#interrupt interrupts}
0765: * the current thread; or
0766: *
0767: * <li>The specified waiting time elapses
0768: *
0769: * </ul>
0770: *
0771: * <p>If the lock is acquired then the value <tt>true</tt> is
0772: * returned and the lock hold count is set to one.
0773: *
0774: * <p>If the current thread:
0775: *
0776: * <ul>
0777: *
0778: * <li>has its interrupted status set on entry to this method;
0779: * or
0780: *
0781: * <li>is {@link Thread#interrupt interrupted} while acquiring
0782: * the lock,
0783: *
0784: * </ul>
0785: *
0786: * then {@link InterruptedException} is thrown and the current
0787: * thread's interrupted status is cleared.
0788: *
0789: * <p>If the specified waiting time elapses then the value
0790: * <tt>false</tt> is returned. If the time is less than or
0791: * equal to zero, the method will not wait at all.
0792: *
0793: * <p>In this implementation, as this method is an explicit
0794: * interruption point, preference is given to responding to
0795: * the interrupt over normal or reentrant acquisition of the
0796: * lock, and over reporting the elapse of the waiting time.
0797: *
0798: * @param timeout the time to wait for the lock
0799: * @param unit the time unit of the timeout argument
0800: *
0801: * @return <tt>true</tt> if the lock was free and was acquired
0802: * by the current thread, or the lock was already held by the
0803: * current thread; and <tt>false</tt> if the waiting time
0804: * elapsed before the lock could be acquired.
0805: *
0806: * @throws InterruptedException if the current thread is interrupted
0807: * @throws NullPointerException if unit is null
0808: *
0809: */
0810: public boolean tryLock(long timeout, TimeUnit unit)
0811: throws InterruptedException {
0812: return sync.tryAcquireNanos(1, unit.toNanos(timeout));
0813: }
0814:
0815: /**
0816: * Attempts to release this lock.
0817: *
0818: * <p>If the current thread is the holder of this lock then
0819: * the hold count is decremented. If the hold count is now
0820: * zero then the lock is released. If the current thread is
0821: * not the holder of this lock then {@link
0822: * IllegalMonitorStateException} is thrown.
0823: * @throws IllegalMonitorStateException if the current thread does not
0824: * hold this lock.
0825: */
0826: public void unlock() {
0827: sync.release(1);
0828: }
0829:
0830: /**
0831: * Returns a {@link Condition} instance for use with this
0832: * {@link Lock} instance.
0833: * <p>The returned {@link Condition} instance supports the same
0834: * usages as do the {@link Object} monitor methods ({@link
0835: * Object#wait() wait}, {@link Object#notify notify}, and {@link
0836: * Object#notifyAll notifyAll}) when used with the built-in
0837: * monitor lock.
0838: *
0839: * <ul>
0840: *
0841: * <li>If this write lock is not held when any {@link
0842: * Condition} method is called then an {@link
0843: * IllegalMonitorStateException} is thrown. (Read locks are
0844: * held independently of write locks, so are not checked or
0845: * affected. However it is essentially always an error to
0846: * invoke a condition waiting method when the current thread
0847: * has also acquired read locks, since other threads that
0848: * could unblock it will not be able to access the write
0849: * lock.)
0850: *
0851: * <li>When the condition {@link Condition#await() waiting}
0852: * methods are called the write lock is released and, before
0853: * they return, the write lock is reacquired and the lock hold
0854: * count restored to what it was when the method was called.
0855: *
0856: * <li>If a thread is {@link Thread#interrupt interrupted} while
0857: * waiting then the wait will terminate, an {@link
0858: * InterruptedException} will be thrown, and the thread's
0859: * interrupted status will be cleared.
0860: *
0861: * <li> Waiting threads are signalled in FIFO order
0862: *
0863: * <li>The ordering of lock reacquisition for threads returning
0864: * from waiting methods is the same as for threads initially
0865: * acquiring the lock, which is in the default case not specified,
0866: * but for <em>fair</em> locks favors those threads that have been
0867: * waiting the longest.
0868: *
0869: * </ul>
0870: * @return the Condition object
0871: */
0872: public Condition newCondition() {
0873: return sync.newCondition();
0874: }
0875:
0876: /**
0877: * Returns a string identifying this lock, as well as its lock
0878: * state. The state, in brackets includes either the String
0879: * "Unlocked" or the String "Locked by"
0880: * followed by the {@link Thread#getName} of the owning thread.
0881: * @return a string identifying this lock, as well as its lock state.
0882: */
0883: public String toString() {
0884: Thread owner = sync.getOwner();
0885: return super .toString()
0886: + ((owner == null) ? "[Unlocked]"
0887: : "[Locked by thread " + owner.getName()
0888: + "]");
0889: }
0890:
0891: }
0892:
0893: // Instrumentation and status
0894:
0895: /**
0896: * Returns true if this lock has fairness set true.
0897: * @return true if this lock has fairness set true.
0898: */
0899: public final boolean isFair() {
0900: return sync instanceof FairSync;
0901: }
0902:
0903: /**
0904: * Returns the thread that currently owns the exclusive lock, or
0905: * <tt>null</tt> if not owned. Note that the owner may be
0906: * momentarily <tt>null</tt> even if there are threads trying to
0907: * acquire the lock but have not yet done so. This method is
0908: * designed to facilitate construction of subclasses that provide
0909: * more extensive lock monitoring facilities.
0910: * @return the owner, or <tt>null</tt> if not owned.
0911: */
0912: protected Thread getOwner() {
0913: return sync.getOwner();
0914: }
0915:
0916: /**
0917: * Queries the number of read locks held for this lock. This
0918: * method is designed for use in monitoring system state, not for
0919: * synchronization control.
0920: * @return the number of read locks held.
0921: */
0922: public int getReadLockCount() {
0923: return sync.getReadLockCount();
0924: }
0925:
0926: /**
0927: * Queries if the write lock is held by any thread. This method is
0928: * designed for use in monitoring system state, not for
0929: * synchronization control.
0930: * @return <tt>true</tt> if any thread holds write lock and
0931: * <tt>false</tt> otherwise.
0932: */
0933: public boolean isWriteLocked() {
0934: return sync.isWriteLocked();
0935: }
0936:
0937: /**
0938: * Queries if the write lock is held by the current thread.
0939: * @return <tt>true</tt> if current thread holds this lock and
0940: * <tt>false</tt> otherwise.
0941: */
0942: public boolean isWriteLockedByCurrentThread() {
0943: return sync.isHeldExclusively();
0944: }
0945:
0946: /**
0947: * Queries the number of reentrant write holds on this lock by the
0948: * current thread. A writer thread has a hold on a lock for
0949: * each lock action that is not matched by an unlock action.
0950: *
0951: * @return the number of holds on this lock by the current thread,
0952: * or zero if this lock is not held by the current thread.
0953: */
0954: public int getWriteHoldCount() {
0955: return sync.getWriteHoldCount();
0956: }
0957:
0958: /**
0959: * Returns a collection containing threads that may be waiting to
0960: * acquire the write lock. Because the actual set of threads may
0961: * change dynamically while constructing this result, the returned
0962: * collection is only a best-effort estimate. The elements of the
0963: * returned collection are in no particular order. This method is
0964: * designed to facilitate construction of subclasses that provide
0965: * more extensive lock monitoring facilities.
0966: * @return the collection of threads
0967: */
0968: protected Collection<Thread> getQueuedWriterThreads() {
0969: return sync.getExclusiveQueuedThreads();
0970: }
0971:
0972: /**
0973: * Returns a collection containing threads that may be waiting to
0974: * acquire the read lock. Because the actual set of threads may
0975: * change dynamically while constructing this result, the returned
0976: * collection is only a best-effort estimate. The elements of the
0977: * returned collection are in no particular order. This method is
0978: * designed to facilitate construction of subclasses that provide
0979: * more extensive lock monitoring facilities.
0980: * @return the collection of threads
0981: */
0982: protected Collection<Thread> getQueuedReaderThreads() {
0983: return sync.getSharedQueuedThreads();
0984: }
0985:
0986: /**
0987: * Queries whether any threads are waiting to acquire. Note that
0988: * because cancellations may occur at any time, a <tt>true</tt>
0989: * return does not guarantee that any other thread will ever
0990: * acquire. This method is designed primarily for use in
0991: * monitoring of the system state.
0992: *
0993: * @return true if there may be other threads waiting to acquire
0994: * the lock.
0995: */
0996: public final boolean hasQueuedThreads() {
0997: return sync.hasQueuedThreads();
0998: }
0999:
1000: /**
1001: * Queries whether the given thread is waiting to acquire this
1002: * lock. Note that because cancellations may occur at any time, a
1003: * <tt>true</tt> return does not guarantee that this thread
1004: * will ever acquire. This method is designed primarily for use
1005: * in monitoring of the system state.
1006: *
1007: * @param thread the thread
1008: * @return true if the given thread is queued waiting for this lock.
1009: * @throws NullPointerException if thread is null
1010: */
1011: public final boolean hasQueuedThread(Thread thread) {
1012: return sync.isQueued(thread);
1013: }
1014:
1015: /**
1016: * Returns an estimate of the number of threads waiting to
1017: * acquire. The value is only an estimate because the number of
1018: * threads may change dynamically while this method traverses
1019: * internal data structures. This method is designed for use in
1020: * monitoring of the system state, not for synchronization
1021: * control.
1022: * @return the estimated number of threads waiting for this lock
1023: */
1024: public final int getQueueLength() {
1025: return sync.getQueueLength();
1026: }
1027:
1028: /**
1029: * Returns a collection containing threads that may be waiting to
1030: * acquire. Because the actual set of threads may change
1031: * dynamically while constructing this result, the returned
1032: * collection is only a best-effort estimate. The elements of the
1033: * returned collection are in no particular order. This method is
1034: * designed to facilitate construction of subclasses that provide
1035: * more extensive monitoring facilities.
1036: * @return the collection of threads
1037: */
1038: protected Collection<Thread> getQueuedThreads() {
1039: return sync.getQueuedThreads();
1040: }
1041:
1042: /**
1043: * Queries whether any threads are waiting on the given condition
1044: * associated with the write lock. Note that because timeouts and
1045: * interrupts may occur at any time, a <tt>true</tt> return does
1046: * not guarantee that a future <tt>signal</tt> will awaken any
1047: * threads. This method is designed primarily for use in
1048: * monitoring of the system state.
1049: * @param condition the condition
1050: * @return <tt>true</tt> if there are any waiting threads.
1051: * @throws IllegalMonitorStateException if this lock
1052: * is not held
1053: * @throws IllegalArgumentException if the given condition is
1054: * not associated with this lock
1055: * @throws NullPointerException if condition null
1056: */
1057: public boolean hasWaiters(Condition condition) {
1058: if (condition == null)
1059: throw new NullPointerException();
1060: if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
1061: throw new IllegalArgumentException("not owner");
1062: return sync
1063: .hasWaiters((AbstractQueuedSynchronizer.ConditionObject) condition);
1064: }
1065:
1066: /**
1067: * Returns an estimate of the number of threads waiting on the
1068: * given condition associated with the write lock. Note that because
1069: * timeouts and interrupts may occur at any time, the estimate
1070: * serves only as an upper bound on the actual number of waiters.
1071: * This method is designed for use in monitoring of the system
1072: * state, not for synchronization control.
1073: * @param condition the condition
1074: * @return the estimated number of waiting threads.
1075: * @throws IllegalMonitorStateException if this lock
1076: * is not held
1077: * @throws IllegalArgumentException if the given condition is
1078: * not associated with this lock
1079: * @throws NullPointerException if condition null
1080: */
1081: public int getWaitQueueLength(Condition condition) {
1082: if (condition == null)
1083: throw new NullPointerException();
1084: if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
1085: throw new IllegalArgumentException("not owner");
1086: return sync
1087: .getWaitQueueLength((AbstractQueuedSynchronizer.ConditionObject) condition);
1088: }
1089:
1090: /**
1091: * Returns a collection containing those threads that may be
1092: * waiting on the given condition associated with the write lock.
1093: * Because the actual set of threads may change dynamically while
1094: * constructing this result, the returned collection is only a
1095: * best-effort estimate. The elements of the returned collection
1096: * are in no particular order. This method is designed to
1097: * facilitate construction of subclasses that provide more
1098: * extensive condition monitoring facilities.
1099: * @param condition the condition
1100: * @return the collection of threads
1101: * @throws IllegalMonitorStateException if this lock
1102: * is not held
1103: * @throws IllegalArgumentException if the given condition is
1104: * not associated with this lock
1105: * @throws NullPointerException if condition null
1106: */
1107: protected Collection<Thread> getWaitingThreads(Condition condition) {
1108: if (condition == null)
1109: throw new NullPointerException();
1110: if (!(condition instanceof AbstractQueuedSynchronizer.ConditionObject))
1111: throw new IllegalArgumentException("not owner");
1112: return sync
1113: .getWaitingThreads((AbstractQueuedSynchronizer.ConditionObject) condition);
1114: }
1115:
1116: /**
1117: * Returns a string identifying this lock, as well as its lock state.
1118: * The state, in brackets, includes the String "Write locks ="
1119: * follwed by the number of reentrantly held write locks, and the
1120: * String "Read locks =" followed by the number of held
1121: * read locks.
1122: * @return a string identifying this lock, as well as its lock state.
1123: */
1124: public String toString() {
1125: int c = sync.getCount();
1126: int w = exclusiveCount(c);
1127: int r = sharedCount(c);
1128:
1129: return super .toString() + "[Write locks = " + w
1130: + ", Read locks = " + r + "]";
1131: }
1132:
1133: }
|