You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by hi...@apache.org on 2009/07/16 16:01:17 UTC
svn commit: r794678 [17/19] - in
/harmony/enhanced/classlib/trunk/modules/concurrent/src:
main/java/java/util/concurrent/ main/java/java/util/concurrent/atomic/
main/java/java/util/concurrent/locks/ test/java/
Modified: harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java?rev=794678&r1=794677&r2=794678&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java (original)
+++ harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/ReentrantReadWriteLock.java Thu Jul 16 14:01:15 2009
@@ -19,32 +19,60 @@
*
* <p> This class does not impose a reader or writer preference
* ordering for lock access. However, it does support an optional
- * <em>fairness</em> policy. When constructed as fair, threads
- * contend for entry using an approximately arrival-order policy. When
- * the write lock is released either the longest-waiting single writer
- * will be assigned the write lock, or if there is a reader waiting
- * longer than any writer, the set of readers will be assigned the
- * read lock. When constructed as non-fair, the order of entry to the
- * lock need not be in arrival order. In either case, if readers are
- * active and a writer enters the lock then no subsequent readers will
- * be granted the read lock until after that writer has acquired and
- * released the write lock.
- *
+ * <em>fairness</em> policy.
+ *
+ * <dl>
+ * <dt><b><i>Non-fair mode (default)</i></b>
+ * <dd>When constructed as non-fair (the default), the order of entry
+ * to the read and write lock is unspecified, subject to reentrancy
+ * constraints. A nonfair lock that is continuously contended may
+ * indefinitely postpone one or more reader or writer threads, but
+ * will normally have higher throughput than a fair lock.
+ * <p>
+ *
+ * <dt><b><i>Fair mode</i></b>
+ * <dd> When constructed as fair, threads contend for entry using an
+ * approximately arrival-order policy. When the currently held lock
+ * is released either the longest-waiting single writer thread will
+ * be assigned the write lock, or if there is a group of reader threads
+ * waiting longer than all waiting writer threads, that group will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair read lock (non-reentrantly)
+ * will block if either the write lock is held, or there is a waiting
+ * writer thread. The thread will not acquire the read lock until
+ * after the oldest currently waiting writer thread has acquired and
+ * released the write lock. Of course, if a waiting writer abandons
+ * its wait, leaving one or more reader threads as the longest waiters
+ * in the queue with the write lock free, then those readers will be
+ * assigned the read lock.
+ *
+ * <p>A thread that tries to acquire a fair write lock (non-reentrantly)
+ * will block unless both the read lock and write lock are free (which
+ * implies there are no waiting threads). (Note that the non-blocking
+ * {@link ReadLock#tryLock()} and {@link WriteLock#tryLock()} methods
+ * do not honor this fair setting and will acquire the lock if it is
+ * possible, regardless of waiting threads.)
+ * <p>
+ * </dl>
+ *
* <li><b>Reentrancy</b>
+ *
* <p>This lock allows both readers and writers to reacquire read or
- * write locks in the style of a {@link ReentrantLock}. Readers are not
- * allowed until all write locks held by the writing thread have been
- * released.
- * <p>Additionally, a writer can acquire the read lock - but not vice-versa.
- * Among other applications, reentrancy can be useful when
- * write locks are held during calls or callbacks to methods that
- * perform reads under read locks.
- * If a reader tries to acquire the write lock it will never succeed.
- *
+ * write locks in the style of a {@link ReentrantLock}. Non-reentrant
+ * readers are not allowed until all write locks held by the writing
+ * thread have been released.
+ *
+ * <p>Additionally, a writer can acquire the read lock, but not
+ * vice-versa. Among other applications, reentrancy can be useful
+ * when write locks are held during calls or callbacks to methods that
+ * perform reads under read locks. If a reader tries to acquire the
+ * write lock it will never succeed.
+ *
* <li><b>Lock downgrading</b>
* <p>Reentrancy also allows downgrading from the write lock to a read lock,
* by acquiring the write lock, then the read lock and then releasing the
- * write lock. However, upgrading from a read lock to the write lock, is
+ * write lock. However, upgrading from a read lock to the write lock is
* <b>not</b> possible.
*
* <li><b>Interruption of lock acquisition</b>
@@ -53,96 +81,105 @@
*
* <li><b>{@link Condition} support</b>
* <p>The write lock provides a {@link Condition} implementation that
- * behaves in the same way, with respect to the write lock, as the
+ * behaves in the same way, with respect to the write lock, as the
* {@link Condition} implementation provided by
* {@link ReentrantLock#newCondition} does for {@link ReentrantLock}.
* This {@link Condition} can, of course, only be used with the write lock.
+ *
* <p>The read lock does not support a {@link Condition} and
- * <tt>readLock().newCondition()</tt> throws
- * <tt>UnsupportedOperationException</tt>.
+ * {@code readLock().newCondition()} throws
+ * {@code UnsupportedOperationException}.
*
* <li><b>Instrumentation</b>
- * <P> This class supports methods to determine whether locks
+ * <p>This class supports methods to determine whether locks
* are held or contended. These methods are designed for monitoring
* system state, not for synchronization control.
* </ul>
*
- * <p> Serialization of this class behaves in the same way as built-in
+ * <p>Serialization of this class behaves in the same way as built-in
* locks: a deserialized lock is in the unlocked state, regardless of
* its state when serialized.
*
- * <p><b>Sample usages</b>. Here is a code sketch showing how to exploit
- * reentrancy to perform lock downgrading after updating a cache (exception
- * handling is elided for simplicity):
- * <pre>
+ * <p><b>Sample usages</b>. Here is a code sketch showing how to perform
+ * lock downgrading after updating a cache (exception handling is
+ * particularly tricky when handling multiple locks in a non-nested
+ * fashion):
+ *
+ * <pre> {@code
* class CachedData {
* Object data;
* volatile boolean cacheValid;
- * ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+ * final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
*
* void processCachedData() {
* rwl.readLock().lock();
* if (!cacheValid) {
- * // upgrade lock manually
- * rwl.readLock().unlock(); // must unlock first to obtain writelock
+ * // Must release read lock before acquiring write lock
+ * rwl.readLock().unlock();
* rwl.writeLock().lock();
- * if (!cacheValid) { // recheck
- * data = ...
- * cacheValid = true;
+ * try {
+ * // Recheck state because another thread might have
+ * // acquired write lock and changed state before we did.
+ * if (!cacheValid) {
+ * data = ...
+ * cacheValid = true;
+ * }
+ * // Downgrade by acquiring read lock before releasing write lock
+ * rwl.readLock().lock();
+ * } finally {
+ * rwl.writeLock().unlock(); // Unlock write, still hold read
* }
- * // downgrade lock
- * rwl.readLock().lock(); // reacquire read without giving up write lock
- * rwl.writeLock().unlock(); // unlock write, still hold read
* }
*
- * use(data);
- * rwl.readLock().unlock();
+ * try {
+ * use(data);
+ * } finally {
+ * rwl.readLock().unlock();
+ * }
* }
- * }
- * </pre>
+ * }}</pre>
*
* ReentrantReadWriteLocks can be used to improve concurrency in some
* uses of some kinds of Collections. This is typically worthwhile
* only when the collections are expected to be large, accessed by
* more reader threads than writer threads, and entail operations with
* overhead that outweighs synchronization overhead. For example, here
- * is a class using a TreeMap that is expected to be large and
+ * is a class using a TreeMap that is expected to be large and
* concurrently accessed.
*
- * <pre>
+ * <pre>{@code
* class RWDictionary {
- * private final Map<String, Data> m = new TreeMap<String, Data>();
+ * private final Map<String, Data> m = new TreeMap<String, Data>();
* private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
* private final Lock r = rwl.readLock();
* private final Lock w = rwl.writeLock();
*
* public Data get(String key) {
- * r.lock(); try { return m.get(key); } finally { r.unlock(); }
+ * r.lock();
+ * try { return m.get(key); }
+ * finally { r.unlock(); }
* }
* public String[] allKeys() {
- * r.lock(); try { return m.keySet().toArray(); } finally { r.unlock(); }
+ * r.lock();
+ * try { return m.keySet().toArray(); }
+ * finally { r.unlock(); }
* }
* public Data put(String key, Data value) {
- * w.lock(); try { return m.put(key, value); } finally { w.unlock(); }
+ * w.lock();
+ * try { return m.put(key, value); }
+ * finally { w.unlock(); }
* }
* public void clear() {
- * w.lock(); try { m.clear(); } finally { w.unlock(); }
+ * w.lock();
+ * try { m.clear(); }
+ * finally { w.unlock(); }
* }
- * }
- * </pre>
- *
+ * }}</pre>
*
* <h3>Implementation Notes</h3>
*
- * <p>A reentrant write lock intrinsically defines an owner and can
- * only be released by the thread that acquired it. In contrast, in
- * this implementation, the read lock has no concept of ownership, and
- * there is no requirement that the thread releasing a read lock is
- * the same as the one that acquired it. However, this property is
- * not guaranteed to hold in future implementations of this class.
- *
- * <p> This lock supports a maximum of 65536 recursive write locks
- * and 65536 read locks. Attempts to exceed these limits result in
+ * <p>This lock supports a maximum of 65535 recursive write locks
+ * and 65535 read locks. Attempts to exceed these limits result in
* {@link Error} throws from locking methods.
*
* @since 1.5
@@ -156,26 +193,24 @@
/** Inner class providing writelock */
private final ReentrantReadWriteLock.WriteLock writerLock;
/** Performs all synchronization mechanics */
- private final Sync sync;
+ final Sync sync;
/**
- * Creates a new <tt>ReentrantReadWriteLock</tt> with
- * default ordering properties.
+ * Creates a new {@code ReentrantReadWriteLock} with
+ * default (nonfair) ordering properties.
*/
public ReentrantReadWriteLock() {
- sync = new NonfairSync();
- readerLock = new ReadLock(this);
- writerLock = new WriteLock(this);
+ this(false);
}
/**
- * Creates a new <tt>ReentrantReadWriteLock</tt> with
+ * Creates a new {@code ReentrantReadWriteLock} with
* the given fairness policy.
*
- * @param fair true if this lock should use a fair ordering policy
+ * @param fair {@code true} if this lock should use a fair ordering policy
*/
public ReentrantReadWriteLock(boolean fair) {
- sync = (fair)? new FairSync() : new NonfairSync();
+ sync = fair ? new FairSync() : new NonfairSync();
readerLock = new ReadLock(this);
writerLock = new WriteLock(this);
}
@@ -183,129 +218,409 @@
public ReentrantReadWriteLock.WriteLock writeLock() { return writerLock; }
public ReentrantReadWriteLock.ReadLock readLock() { return readerLock; }
- /*
- * Read vs write count extraction constants and functions.
- * Lock state is logically divided into two shorts: The lower
- * one representing the exclusive (writer) lock hold count,
- * and the upper the shared (reader) hold count.
- */
-
- static final int SHARED_SHIFT = 16;
- static final int SHARED_UNIT = (1 << SHARED_SHIFT);
- static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
-
- /** Returns the number of shared holds represented in count */
- static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
- /** Returns the number of exclusive holds represented in count */
- static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
-
- /**
+ /**
* Synchronization implementation for ReentrantReadWriteLock.
* Subclassed into fair and nonfair versions.
*/
- abstract static class Sync extends AbstractQueuedSynchronizer {
- /** Current (exclusive) owner thread */
- transient Thread owner;
+ static abstract class Sync extends AbstractQueuedSynchronizer {
+ private static final long serialVersionUID = 6317671515068378041L;
+
+ /*
+ * Read vs write count extraction constants and functions.
+ * Lock state is logically divided into two unsigned shorts:
+ * The lower one representing the exclusive (writer) lock hold count,
+ * and the upper the shared (reader) hold count.
+ */
+
+ static final int SHARED_SHIFT = 16;
+ static final int SHARED_UNIT = (1 << SHARED_SHIFT);
+ static final int MAX_COUNT = (1 << SHARED_SHIFT) - 1;
+ static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;
+
+ /** Returns the number of shared holds represented in count */
+ static int sharedCount(int c) { return c >>> SHARED_SHIFT; }
+ /** Returns the number of exclusive holds represented in count */
+ static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }
/**
- * Perform write lock. Allows fast path in non-fair version.
+ * A counter for per-thread read hold counts.
+ * Maintained as a ThreadLocal; cached in cachedHoldCounter
*/
- abstract void wlock();
+ static final class HoldCounter {
+ int count = 0;
+ // Use id, not reference, to avoid garbage retention
+ final long tid = Thread.currentThread().getId();
+ }
- /**
- * Perform non-fair tryLock for write. tryAcquire is
- * implemented in subclasses, but both versions need nonfair
- * try for trylock method
+ /**
+ * ThreadLocal subclass. Easiest to explicitly define for sake
+ * of deserialization mechanics.
*/
- final boolean nonfairTryAcquire(int acquires) {
- // mask out readlocks if called from condition methods
- acquires = exclusiveCount(acquires);
+ static final class ThreadLocalHoldCounter
+ extends ThreadLocal<HoldCounter> {
+ public HoldCounter initialValue() {
+ return new HoldCounter();
+ }
+ }
+
+ /**
+ * The number of reentrant read locks held by current thread.
+ * Initialized only in constructor and readObject.
+ * Removed whenever a thread's read hold count drops to 0.
+ */
+ private transient ThreadLocalHoldCounter readHolds;
+
+ /**
+ * The hold count of the last thread to successfully acquire
+ * readLock. This saves ThreadLocal lookup in the common case
+ * where the next thread to release is the last one to
+ * acquire. This is non-volatile since it is just used
+ * as a heuristic, and would be great for threads to cache.
+ *
+ * <p>Can outlive the Thread for which it is caching the read
+ * hold count, but avoids garbage retention by not retaining a
+ * reference to the Thread.
+ *
+ * <p>Accessed via a benign data race; relies on the memory
+ * model's final field and out-of-thin-air guarantees.
+ */
+ private transient HoldCounter cachedHoldCounter;
+
+ /**
+ * firstReader is the first thread to have acquired the read lock.
+ * firstReaderHoldCount is firstReader's hold count.
+ *
+ * <p>More precisely, firstReader is the unique thread that last
+ * changed the shared count from 0 to 1, and has not released the
+ * read lock since then; null if there is no such thread.
+ *
+ * <p>Cannot cause garbage retention unless the thread terminated
+ * without relinquishing its read locks, since tryReleaseShared
+ * sets it to null.
+ *
+ * <p>Accessed via a benign data race; relies on the memory
+ * model's out-of-thin-air guarantees for references.
+ *
+ * <p>This allows tracking of read holds for uncontended read
+ * locks to be very cheap.
+ */
+ private transient Thread firstReader = null;
+ private transient int firstReaderHoldCount;
+
+ Sync() {
+ readHolds = new ThreadLocalHoldCounter();
+ setState(getState()); // ensures visibility of readHolds
+ }
+
+ /*
+ * Acquires and releases use the same code for fair and
+ * nonfair locks, but differ in whether/how they allow barging
+ * when queues are non-empty.
+ */
+
+ /**
+ * Returns true if the current thread, when trying to acquire
+ * the read lock, and otherwise eligible to do so, should block
+ * because of policy for overtaking other waiting threads.
+ */
+ abstract boolean readerShouldBlock();
+
+ /**
+ * Returns true if the current thread, when trying to acquire
+ * the write lock, and otherwise eligible to do so, should block
+ * because of policy for overtaking other waiting threads.
+ */
+ abstract boolean writerShouldBlock();
+
+ /*
+ * Note that tryRelease and tryAcquire can be called by
+ * Conditions. So it is possible that their arguments contain
+ * both read and write holds that are all released during a
+ * condition wait and re-established in tryAcquire.
+ */
+
+ protected final boolean tryRelease(int releases) {
+ if (!isHeldExclusively())
+ throw new IllegalMonitorStateException();
+ int nextc = getState() - releases;
+ boolean free = exclusiveCount(nextc) == 0;
+ if (free)
+ setExclusiveOwnerThread(null);
+ setState(nextc);
+ return free;
+ }
+
+ protected final boolean tryAcquire(int acquires) {
+ /*
+ * Walkthrough:
+ * 1. If read count nonzero or write count nonzero
+ * and owner is a different thread, fail.
+ * 2. If count would saturate, fail. (This can only
+ * happen if count is already nonzero.)
+ * 3. Otherwise, this thread is eligible for lock if
+ * it is either a reentrant acquire or
+ * queue policy allows it. If so, update state
+ * and set owner.
+ */
Thread current = Thread.currentThread();
int c = getState();
int w = exclusiveCount(c);
- if (w + acquires >= SHARED_UNIT)
- throw new Error("Maximum lock count exceeded");
- if (c != 0 && (w == 0 || current != owner))
- return false;
- if (!compareAndSetState(c, c + acquires))
+ if (c != 0) {
+ // (Note: if c != 0 and w == 0 then shared count != 0)
+ if (w == 0 || current != getExclusiveOwnerThread())
+ return false;
+ if (w + exclusiveCount(acquires) > MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ // Reentrant acquire
+ setState(c + acquires);
+ return true;
+ }
+ if (writerShouldBlock() ||
+ !compareAndSetState(c, c + acquires))
return false;
- owner = current;
+ setExclusiveOwnerThread(current);
return true;
}
- /**
- * Perform nonfair tryLock for read.
+ protected final boolean tryReleaseShared(int unused) {
+ Thread current = Thread.currentThread();
+ if (firstReader == current) {
+ // assert firstReaderHoldCount > 0;
+ if (firstReaderHoldCount == 1)
+ firstReader = null;
+ else
+ firstReaderHoldCount--;
+ } else {
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ rh = readHolds.get();
+ int count = rh.count;
+ if (count <= 1) {
+ readHolds.remove();
+ if (count <= 0)
+ throw unmatchedUnlockException();
+ }
+ --rh.count;
+ }
+ for (;;) {
+ int c = getState();
+ int nextc = c - SHARED_UNIT;
+ if (compareAndSetState(c, nextc))
+ // Releasing the read lock has no effect on readers,
+ // but it may allow waiting writers to proceed if
+ // both read and write locks are now free.
+ return nextc == 0;
+ }
+ }
+
+ private IllegalMonitorStateException unmatchedUnlockException() {
+ return new IllegalMonitorStateException(
+ "attempt to unlock read lock, not locked by current thread");
+ }
+
+ protected final int tryAcquireShared(int unused) {
+ /*
+ * Walkthrough:
+ * 1. If write lock held by another thread, fail.
+ * 2. Otherwise, this thread is eligible for
+ * lock wrt state, so ask if it should block
+ * because of queue policy. If not, try
+ * to grant by CASing state and updating count.
+ * Note that step does not check for reentrant
+ * acquires, which is postponed to full version
+ * to avoid having to check hold count in
+ * the more typical non-reentrant case.
+ * 3. If step 2 fails either because thread
+ * apparently not eligible or CAS fails or count
+ * saturated, chain to version with full retry loop.
+ */
+ Thread current = Thread.currentThread();
+ int c = getState();
+ if (exclusiveCount(c) != 0 &&
+ getExclusiveOwnerThread() != current)
+ return -1;
+ int r = sharedCount(c);
+ if (!readerShouldBlock() &&
+ r < MAX_COUNT &&
+ compareAndSetState(c, c + SHARED_UNIT)) {
+ if (r == 0) {
+ firstReader = current;
+ firstReaderHoldCount = 1;
+ } else if (firstReader == current) {
+ firstReaderHoldCount++;
+ } else {
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ cachedHoldCounter = rh = readHolds.get();
+ else if (rh.count == 0)
+ readHolds.set(rh);
+ rh.count++;
+ }
+ return 1;
+ }
+ return fullTryAcquireShared(current);
+ }
+
+ /**
+ * Full version of acquire for reads, that handles CAS misses
+ * and reentrant reads not dealt with in tryAcquireShared.
*/
- final int nonfairTryAcquireShared(int acquires) {
+ final int fullTryAcquireShared(Thread current) {
+ /*
+ * This code is in part redundant with that in
+ * tryAcquireShared but is simpler overall by not
+ * complicating tryAcquireShared with interactions between
+ * retries and lazily reading hold counts.
+ */
+ HoldCounter rh = null;
for (;;) {
int c = getState();
- int nextc = c + (acquires << SHARED_SHIFT);
- if (nextc < c)
+ if (exclusiveCount(c) != 0) {
+ if (getExclusiveOwnerThread() != current)
+ return -1;
+ // else we hold the exclusive lock; blocking here
+ // would cause deadlock.
+ } else if (readerShouldBlock()) {
+ // Make sure we're not acquiring read lock reentrantly
+ if (firstReader == current) {
+ // assert firstReaderHoldCount > 0;
+ } else {
+ if (rh == null) {
+ rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId()) {
+ rh = readHolds.get();
+ if (rh.count == 0)
+ readHolds.remove();
+ }
+ }
+ if (rh.count == 0)
+ return -1;
+ }
+ }
+ if (sharedCount(c) == MAX_COUNT)
throw new Error("Maximum lock count exceeded");
- if (exclusiveCount(c) != 0 &&
- owner != Thread.currentThread())
- return -1;
- if (compareAndSetState(c, nextc))
+ if (compareAndSetState(c, c + SHARED_UNIT)) {
+ if (sharedCount(c) == 0) {
+ firstReader = current;
+ firstReaderHoldCount = 1;
+ } else if (firstReader == current) {
+ firstReaderHoldCount++;
+ } else {
+ if (rh == null)
+ rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ rh = readHolds.get();
+ else if (rh.count == 0)
+ readHolds.set(rh);
+ rh.count++;
+ cachedHoldCounter = rh; // cache for release
+ }
return 1;
- // Recheck count if lost CAS
+ }
}
}
- protected final boolean tryRelease(int releases) {
+ /**
+ * Performs tryLock for write, enabling barging in both modes.
+ * This is identical in effect to tryAcquire except for lack
+ * of calls to writerShouldBlock.
+ */
+ final boolean tryWriteLock() {
Thread current = Thread.currentThread();
int c = getState();
- if (owner != current)
- throw new IllegalMonitorStateException();
- int nextc = c - releases;
- boolean free = false;
- if (exclusiveCount(c) == releases) {
- free = true;
- owner = null;
+ if (c != 0) {
+ int w = exclusiveCount(c);
+ if (w == 0 || current != getExclusiveOwnerThread())
+ return false;
+ if (w == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
}
- setState(nextc);
- return free;
+ if (!compareAndSetState(c, c + 1))
+ return false;
+ setExclusiveOwnerThread(current);
+ return true;
}
- protected final boolean tryReleaseShared(int releases) {
+ /**
+ * Performs tryLock for read, enabling barging in both modes.
+ * This is identical in effect to tryAcquireShared except for
+ * lack of calls to readerShouldBlock.
+ */
+ final boolean tryReadLock() {
+ Thread current = Thread.currentThread();
for (;;) {
int c = getState();
- int nextc = c - (releases << SHARED_SHIFT);
- if (nextc < 0)
- throw new IllegalMonitorStateException();
- if (compareAndSetState(c, nextc))
- return nextc == 0;
+ if (exclusiveCount(c) != 0 &&
+ getExclusiveOwnerThread() != current)
+ return false;
+ int r = sharedCount(c);
+ if (r == MAX_COUNT)
+ throw new Error("Maximum lock count exceeded");
+ if (compareAndSetState(c, c + SHARED_UNIT)) {
+ if (r == 0) {
+ firstReader = current;
+ firstReaderHoldCount = 1;
+ } else if (firstReader == current) {
+ firstReaderHoldCount++;
+ } else {
+ HoldCounter rh = cachedHoldCounter;
+ if (rh == null || rh.tid != current.getId())
+ cachedHoldCounter = rh = readHolds.get();
+ else if (rh.count == 0)
+ readHolds.set(rh);
+ rh.count++;
+ }
+ return true;
+ }
}
}
-
+
protected final boolean isHeldExclusively() {
- return exclusiveCount(getState()) != 0 &&
- owner == Thread.currentThread();
+ // While we must in general read state before owner,
+ // we don't need to do so to check if current thread is owner
+ return getExclusiveOwnerThread() == Thread.currentThread();
}
// Methods relayed to outer class
-
- final ConditionObject newCondition() {
- return new ConditionObject();
+
+ final ConditionObject newCondition() {
+ return new ConditionObject();
}
final Thread getOwner() {
- int c = exclusiveCount(getState());
- Thread o = owner;
- return (c == 0)? null : o;
+ // Must read state before owner to ensure memory consistency
+ return ((exclusiveCount(getState()) == 0)?
+ null :
+ getExclusiveOwnerThread());
}
-
+
final int getReadLockCount() {
return sharedCount(getState());
}
-
+
final boolean isWriteLocked() {
return exclusiveCount(getState()) != 0;
}
final int getWriteHoldCount() {
- int c = exclusiveCount(getState());
- Thread o = owner;
- return (o == Thread.currentThread())? c : 0;
+ return isHeldExclusively() ? exclusiveCount(getState()) : 0;
+ }
+
+ final int getReadHoldCount() {
+ if (getReadLockCount() == 0)
+ return 0;
+
+ Thread current = Thread.currentThread();
+ if (firstReader == current)
+ return firstReaderHoldCount;
+
+ HoldCounter rh = cachedHoldCounter;
+ if (rh != null && rh.tid == current.getId())
+ return rh.count;
+
+ int count = readHolds.get().count;
+ if (count == 0) readHolds.remove();
+ return count;
}
/**
@@ -315,78 +630,43 @@
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
s.defaultReadObject();
+ readHolds = new ThreadLocalHoldCounter();
setState(0); // reset to unlocked state
}
final int getCount() { return getState(); }
}
- /**
+ /**
* Nonfair version of Sync
*/
final static class NonfairSync extends Sync {
- protected final boolean tryAcquire(int acquires) {
- return nonfairTryAcquire(acquires);
- }
-
- protected final int tryAcquireShared(int acquires) {
- return nonfairTryAcquireShared(acquires);
- }
-
- // Use fastpath for main write lock method
- final void wlock() {
- if (compareAndSetState(0, 1))
- owner = Thread.currentThread();
- else
- acquire(1);
+ private static final long serialVersionUID = -8159625535654395037L;
+ final boolean writerShouldBlock() {
+ return false; // writers can always barge
+ }
+ final boolean readerShouldBlock() {
+ /* As a heuristic to avoid indefinite writer starvation,
+ * block if the thread that momentarily appears to be head
+ * of queue, if one exists, is a waiting writer. This is
+ * only a probabilistic effect since a new reader will not
+ * block if there is a waiting writer behind other enabled
+ * readers that have not yet drained from the queue.
+ */
+ return apparentlyFirstQueuedIsExclusive();
}
}
- /**
+ /**
* Fair version of Sync
*/
final static class FairSync extends Sync {
- protected final boolean tryAcquire(int acquires) {
- // mask out readlocks if called from condition methods
- acquires = exclusiveCount(acquires);
- Thread current = Thread.currentThread();
- Thread first;
- int c = getState();
- int w = exclusiveCount(c);
- if (w + acquires >= SHARED_UNIT)
- throw new Error("Maximum lock count exceeded");
- if ((w == 0 || current != owner) &&
- (c != 0 ||
- ((first = getFirstQueuedThread()) != null &&
- first != current)))
- return false;
- if (!compareAndSetState(c, c + acquires))
- return false;
- owner = current;
- return true;
- }
-
- protected final int tryAcquireShared(int acquires) {
- Thread current = Thread.currentThread();
- for (;;) {
- Thread first = getFirstQueuedThread();
- if (first != null && first != current)
- return -1;
- int c = getState();
- int nextc = c + (acquires << SHARED_SHIFT);
- if (nextc < c)
- throw new Error("Maximum lock count exceeded");
- if (exclusiveCount(c) != 0 &&
- owner != Thread.currentThread())
- return -1;
- if (compareAndSetState(c, nextc))
- return 1;
- // Recheck count if lost CAS
- }
+ private static final long serialVersionUID = -2274990926593161451L;
+ final boolean writerShouldBlock() {
+ return hasQueuedPredecessors();
}
-
- final void wlock() { // no fast path
- acquire(1);
+ final boolean readerShouldBlock() {
+ return hasQueuedPredecessors();
}
}
@@ -396,46 +676,47 @@
public static class ReadLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -5992448646407690164L;
private final Sync sync;
-
- /**
- * Constructor for use by subclasses.
+
+ /**
+ * Constructor for use by subclasses
+ *
* @param lock the outer lock object
- * @throws NullPointerException if lock null
+ * @throws NullPointerException if the lock is null
*/
protected ReadLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
/**
- * Acquires the shared lock.
+ * Acquires the read lock.
*
- * <p>Acquires the lock if it is not held exclusively by
+ * <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately.
*
- * <p>If the lock is held exclusively by another thread then
+ * <p>If the write lock is held by another thread then
* the current thread becomes disabled for thread scheduling
- * purposes and lies dormant until the lock has been acquired.
+ * purposes and lies dormant until the read lock has been acquired.
*/
- public void lock() {
+ public void lock() {
sync.acquireShared(1);
}
/**
- * Acquires the shared lock unless the current thread is
- * {@link Thread#interrupt interrupted}.
+ * Acquires the read lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
*
- * <p>Acquires the shared lock if it is not held exclusively
+ * <p>Acquires the read lock if the write lock is not held
* by another thread and returns immediately.
*
- * <p>If the lock is held by another thread then the
- * current thread becomes disabled for thread scheduling
+ * <p>If the write lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
* purposes and lies dormant until one of two things happens:
*
* <ul>
*
- * <li>The lock is acquired by the current thread; or
+ * <li>The read lock is acquired by the current thread; or
*
- * <li>Some other thread {@link Thread#interrupt interrupts}
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread.
*
* </ul>
@@ -444,10 +725,10 @@
*
* <ul>
*
- * <li>has its interrupted status set on entry to this method; or
+ * <li>has its interrupted status set on entry to this method; or
*
- * <li>is {@link Thread#interrupt interrupted} while acquiring
- * the lock,
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the read lock,
*
* </ul>
*
@@ -466,83 +747,83 @@
}
/**
- * Acquires the shared lock only if it is not held exclusively by
+ * Acquires the read lock only if the write lock is not held by
* another thread at the time of invocation.
*
- * <p>Acquires the lock if it is not held exclusively by
+ * <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately with the value
- * <tt>true</tt>. Even when this lock has been set to use a
- * fair ordering policy, a call to <tt>tryLock()</tt>
- * <em>will</em> immediately acquire the lock if it is
+ * {@code true}. Even when this lock has been set to use a
+ * fair ordering policy, a call to {@code tryLock()}
+ * <em>will</em> immediately acquire the read lock if it is
* available, whether or not other threads are currently
- * waiting for the lock. This "barging" behavior
+ * waiting for the read lock. This "barging" behavior
* can be useful in certain circumstances, even though it
* breaks fairness. If you want to honor the fairness setting
* for this lock, then use {@link #tryLock(long, TimeUnit)
* tryLock(0, TimeUnit.SECONDS) } which is almost equivalent
* (it also detects interruption).
*
- * <p>If the lock is held exclusively by another thread then
+ * <p>If the write lock is held by another thread then
* this method will return immediately with the value
- * <tt>false</tt>.
+ * {@code false}.
*
- * @return <tt>true</tt> if the lock was acquired.
+ * @return {@code true} if the read lock was acquired
*/
public boolean tryLock() {
- return sync.nonfairTryAcquireShared(1) >= 0;
+ return sync.tryReadLock();
}
/**
- * Acquires the shared lock if it is not held exclusively by
+ * Acquires the read lock if the write lock is not held by
* another thread within the given waiting time and the
- * current thread has not been {@link Thread#interrupt
+ * current thread has not been {@linkplain Thread#interrupt
* interrupted}.
*
- * <p>Acquires the lock if it is not held exclusively by
+ * <p>Acquires the read lock if the write lock is not held by
* another thread and returns immediately with the value
- * <tt>true</tt>. If this lock has been set to use a fair
+ * {@code true}. If this lock has been set to use a fair
* ordering policy then an available lock <em>will not</em> be
* acquired if any other threads are waiting for the
* lock. This is in contrast to the {@link #tryLock()}
- * method. If you want a timed <tt>tryLock</tt> that does
+ * method. If you want a timed {@code tryLock} that does
* permit barging on a fair lock then combine the timed and
* un-timed forms together:
*
* <pre>if (lock.tryLock() || lock.tryLock(timeout, unit) ) { ... }
* </pre>
*
- * <p>If the lock is held exclusively by another thread then the
- * current thread becomes disabled for thread scheduling
+ * <p>If the write lock is held by another thread then the
+ * current thread becomes disabled for thread scheduling
* purposes and lies dormant until one of three things happens:
*
* <ul>
*
- * <li>The lock is acquired by the current thread; or
+ * <li>The read lock is acquired by the current thread; or
*
- * <li>Some other thread {@link Thread#interrupt interrupts} the current
- * thread; or
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
+ * the current thread; or
*
- * <li>The specified waiting time elapses
+ * <li>The specified waiting time elapses.
*
* </ul>
*
- * <p>If the lock is acquired then the value <tt>true</tt> is
+ * <p>If the read lock is acquired then the value {@code true} is
* returned.
*
* <p>If the current thread:
*
* <ul>
*
- * <li>has its interrupted status set on entry to this method; or
+ * <li>has its interrupted status set on entry to this method; or
*
- * <li>is {@link Thread#interrupt interrupted} while acquiring
- * the lock,
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the read lock,
*
* </ul> then {@link InterruptedException} is thrown and the
* current thread's interrupted status is cleared.
*
* <p>If the specified waiting time elapses then the value
- * <tt>false</tt> is returned. If the time is less than or
+ * {@code false} is returned. If the time is less than or
* equal to zero, the method will not wait at all.
*
* <p>In this implementation, as this method is an explicit
@@ -550,13 +831,11 @@
* the interrupt over normal or reentrant acquisition of the
* lock, and over reporting the elapse of the waiting time.
*
- * @param timeout the time to wait for the lock
+ * @param timeout the time to wait for the read lock
* @param unit the time unit of the timeout argument
- *
- * @return <tt>true</tt> if the lock was acquired.
- *
+ * @return {@code true} if the read lock was acquired
* @throws InterruptedException if the current thread is interrupted
- * @throws NullPointerException if unit is null
+ * @throws NullPointerException if the time unit is null
*
*/
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
@@ -564,20 +843,19 @@
}
/**
- * Attempts to release this lock.
+ * Attempts to release this lock.
*
* <p> If the number of readers is now zero then the lock
- * is made available for other lock attempts.
+ * is made available for write lock attempts.
*/
public void unlock() {
sync.releaseShared(1);
}
/**
- * Throws UnsupportedOperationException because ReadLocks
- * do not support conditions.
- * @return A new {@link Condition} instance for this <tt>Lock</tt>
- * instance.
+ * Throws {@code UnsupportedOperationException} because
+ * {@code ReadLocks} do not support conditions.
+ *
* @throws UnsupportedOperationException always
*/
public Condition newCondition() {
@@ -586,17 +864,16 @@
/**
* Returns a string identifying this lock, as well as its lock state.
- * The state, in brackets, includes the String
- * "Read locks =" followed by the number of held
- * read locks.
- * @return a string identifying this lock, as well as its lock state.
+ * The state, in brackets, includes the String {@code "Read locks ="}
+ * followed by the number of held read locks.
+ *
+ * @return a string identifying this lock, as well as its lock state
*/
public String toString() {
int r = sync.getReadLockCount();
- return super.toString() +
+ return super.toString() +
"[Read locks = " + r + "]";
}
-
}
/**
@@ -605,42 +882,45 @@
public static class WriteLock implements Lock, java.io.Serializable {
private static final long serialVersionUID = -4992448646407690164L;
private final Sync sync;
-
- /**
- * Constructor for use by subclasses.
+
+ /**
+ * Constructor for use by subclasses
+ *
* @param lock the outer lock object
- * @throws NullPointerException if lock null
+ * @throws NullPointerException if the lock is null
*/
protected WriteLock(ReentrantReadWriteLock lock) {
sync = lock.sync;
}
/**
- * Acquire the lock.
+ * Acquires the write lock.
*
- * <p>Acquires the lock if it is not held by another thread
- * and returns immediately, setting the lock hold count to
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately, setting the write lock hold count to
* one.
*
- * <p>If the current thread already holds the lock then the
+ * <p>If the current thread already holds the write lock then the
* hold count is incremented by one and the method returns
* immediately.
*
* <p>If the lock is held by another thread then the current
* thread becomes disabled for thread scheduling purposes and
- * lies dormant until the lock has been acquired, at which
- * time the lock hold count is set to one.
+ * lies dormant until the write lock has been acquired, at which
+ * time the write lock hold count is set to one.
*/
public void lock() {
- sync.wlock();
+ sync.acquire(1);
}
/**
- * Acquires the lock unless the current thread is {@link
- * Thread#interrupt interrupted}.
+ * Acquires the write lock unless the current thread is
+ * {@linkplain Thread#interrupt interrupted}.
*
- * <p>Acquires the lock if it is not held by another thread
- * and returns immediately, setting the lock hold count to
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately, setting the write lock hold count to
* one.
*
* <p>If the current thread already holds this lock then the
@@ -653,14 +933,14 @@
*
* <ul>
*
- * <li>The lock is acquired by the current thread; or
+ * <li>The write lock is acquired by the current thread; or
*
- * <li>Some other thread {@link Thread#interrupt interrupts}
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread.
*
* </ul>
*
- * <p>If the lock is acquired by the current thread then the
+ * <p>If the write lock is acquired by the current thread then the
* lock hold count is set to one.
*
* <p>If the current thread:
@@ -670,8 +950,8 @@
* <li>has its interrupted status set on entry to this method;
* or
*
- * <li>is {@link Thread#interrupt interrupted} while acquiring
- * the lock,
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the write lock,
*
* </ul>
*
@@ -690,16 +970,17 @@
}
/**
- * Acquires the lock only if it is not held by another thread
+ * Acquires the write lock only if it is not held by another thread
* at the time of invocation.
*
- * <p>Acquires the lock if it is not held by another thread
- * and returns immediately with the value <tt>true</tt>,
- * setting the lock hold count to one. Even when this lock has
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately with the value {@code true},
+ * setting the write lock hold count to one. Even when this lock has
* been set to use a fair ordering policy, a call to
- * <tt>tryLock()</tt> <em>will</em> immediately acquire the
+ * {@code tryLock()} <em>will</em> immediately acquire the
* lock if it is available, whether or not other threads are
- * currently waiting for the lock. This "barging"
+ * currently waiting for the write lock. This "barging"
* behavior can be useful in certain circumstances, even
* though it breaks fairness. If you want to honor the
* fairness setting for this lock, then use {@link
@@ -708,31 +989,32 @@
*
* <p> If the current thread already holds this lock then the
* hold count is incremented by one and the method returns
- * <tt>true</tt>.
+ * {@code true}.
*
* <p>If the lock is held by another thread then this method
- * will return immediately with the value <tt>false</tt>.
+ * will return immediately with the value {@code false}.
*
- * @return <tt>true</tt> if the lock was free and was acquired by the
- * current thread, or the lock was already held by the current thread; and
- * <tt>false</tt> otherwise.
+ * @return {@code true} if the lock was free and was acquired
+ * by the current thread, or the write lock was already held
+ * by the current thread; and {@code false} otherwise.
*/
public boolean tryLock( ) {
- return sync.nonfairTryAcquire(1);
+ return sync.tryWriteLock();
}
/**
- * Acquires the lock if it is not held by another thread
+ * Acquires the write lock if it is not held by another thread
* within the given waiting time and the current thread has
- * not been {@link Thread#interrupt interrupted}.
+ * not been {@linkplain Thread#interrupt interrupted}.
*
- * <p>Acquires the lock if it is not held by another thread
- * and returns immediately with the value <tt>true</tt>,
- * setting the lock hold count to one. If this lock has been
+ * <p>Acquires the write lock if neither the read nor write lock
+ * are held by another thread
+ * and returns immediately with the value {@code true},
+ * setting the write lock hold count to one. If this lock has been
* set to use a fair ordering policy then an available lock
* <em>will not</em> be acquired if any other threads are
- * waiting for the lock. This is in contrast to the {@link
- * #tryLock()} method. If you want a timed <tt>tryLock</tt>
+ * waiting for the write lock. This is in contrast to the {@link
+ * #tryLock()} method. If you want a timed {@code tryLock}
* that does permit barging on a fair lock then combine the
* timed and un-timed forms together:
*
@@ -741,7 +1023,7 @@
*
* <p>If the current thread already holds this lock then the
* hold count is incremented by one and the method returns
- * <tt>true</tt>.
+ * {@code true}.
*
* <p>If the lock is held by another thread then the current
* thread becomes disabled for thread scheduling purposes and
@@ -749,17 +1031,17 @@
*
* <ul>
*
- * <li>The lock is acquired by the current thread; or
+ * <li>The write lock is acquired by the current thread; or
*
- * <li>Some other thread {@link Thread#interrupt interrupts}
+ * <li>Some other thread {@linkplain Thread#interrupt interrupts}
* the current thread; or
*
* <li>The specified waiting time elapses
*
* </ul>
*
- * <p>If the lock is acquired then the value <tt>true</tt> is
- * returned and the lock hold count is set to one.
+ * <p>If the write lock is acquired then the value {@code true} is
+ * returned and the write lock hold count is set to one.
*
* <p>If the current thread:
*
@@ -768,16 +1050,16 @@
* <li>has its interrupted status set on entry to this method;
* or
*
- * <li>is {@link Thread#interrupt interrupted} while acquiring
- * the lock,
+ * <li>is {@linkplain Thread#interrupt interrupted} while
+ * acquiring the write lock,
*
- * </ul>
+ * </ul>
*
* then {@link InterruptedException} is thrown and the current
* thread's interrupted status is cleared.
*
* <p>If the specified waiting time elapses then the value
- * <tt>false</tt> is returned. If the time is less than or
+ * {@code false} is returned. If the time is less than or
* equal to zero, the method will not wait at all.
*
* <p>In this implementation, as this method is an explicit
@@ -785,30 +1067,31 @@
* the interrupt over normal or reentrant acquisition of the
* lock, and over reporting the elapse of the waiting time.
*
- * @param timeout the time to wait for the lock
+ * @param timeout the time to wait for the write lock
* @param unit the time unit of the timeout argument
*
- * @return <tt>true</tt> if the lock was free and was acquired
- * by the current thread, or the lock was already held by the
- * current thread; and <tt>false</tt> if the waiting time
+ * @return {@code true} if the lock was free and was acquired
+ * by the current thread, or the write lock was already held by the
+ * current thread; and {@code false} if the waiting time
* elapsed before the lock could be acquired.
*
* @throws InterruptedException if the current thread is interrupted
- * @throws NullPointerException if unit is null
+ * @throws NullPointerException if the time unit is null
*
*/
public boolean tryLock(long timeout, TimeUnit unit) throws InterruptedException {
return sync.tryAcquireNanos(1, unit.toNanos(timeout));
}
-
+
/**
- * Attempts to release this lock.
+ * Attempts to release this lock.
*
* <p>If the current thread is the holder of this lock then
* the hold count is decremented. If the hold count is now
* zero then the lock is released. If the current thread is
* not the holder of this lock then {@link
* IllegalMonitorStateException} is thrown.
+ *
* @throws IllegalMonitorStateException if the current thread does not
* hold this lock.
*/
@@ -818,7 +1101,7 @@
/**
* Returns a {@link Condition} instance for use with this
- * {@link Lock} instance.
+ * {@link Lock} instance.
* <p>The returned {@link Condition} instance supports the same
* usages as do the {@link Object} monitor methods ({@link
* Object#wait() wait}, {@link Object#notify notify}, and {@link
@@ -834,74 +1117,80 @@
* affected. However it is essentially always an error to
* invoke a condition waiting method when the current thread
* has also acquired read locks, since other threads that
- * could unblock it will not be able to access the write
+ * could unblock it will not be able to acquire the write
* lock.)
*
- * <li>When the condition {@link Condition#await() waiting}
+ * <li>When the condition {@linkplain Condition#await() waiting}
* methods are called the write lock is released and, before
* they return, the write lock is reacquired and the lock hold
* count restored to what it was when the method was called.
*
- * <li>If a thread is {@link Thread#interrupt interrupted} while
+ * <li>If a thread is {@linkplain Thread#interrupt interrupted} while
* waiting then the wait will terminate, an {@link
* InterruptedException} will be thrown, and the thread's
* interrupted status will be cleared.
*
- * <li> Waiting threads are signalled in FIFO order
+ * <li> Waiting threads are signalled in FIFO order.
*
* <li>The ordering of lock reacquisition for threads returning
* from waiting methods is the same as for threads initially
* acquiring the lock, which is in the default case not specified,
* but for <em>fair</em> locks favors those threads that have been
* waiting the longest.
- *
+ *
* </ul>
+ *
* @return the Condition object
*/
- public Condition newCondition() {
+ public Condition newCondition() {
return sync.newCondition();
}
/**
* Returns a string identifying this lock, as well as its lock
* state. The state, in brackets includes either the String
- * "Unlocked" or the String "Locked by"
- * followed by the {@link Thread#getName} of the owning thread.
- * @return a string identifying this lock, as well as its lock state.
+ * {@code "Unlocked"} or the String {@code "Locked by"}
+ * followed by the {@linkplain Thread#getName name} of the owning thread.
+ *
+ * @return a string identifying this lock, as well as its lock state
*/
public String toString() {
- Thread owner = sync.getOwner();
- return super.toString() + ((owner == null) ?
+ Thread o = sync.getOwner();
+ return super.toString() + ((o == null) ?
"[Unlocked]" :
- "[Locked by thread " + owner.getName() + "]");
+ "[Locked by thread " + o.getName() + "]");
}
}
-
// Instrumentation and status
/**
- * Returns true if this lock has fairness set true.
- * @return true if this lock has fairness set true.
+ * Returns {@code true} if this lock has fairness set true.
+ *
+ * @return {@code true} if this lock has fairness set true
*/
public final boolean isFair() {
return sync instanceof FairSync;
}
/**
- * Returns the thread that currently owns the exclusive lock, or
- * <tt>null</tt> if not owned. Note that the owner may be
- * momentarily <tt>null</tt> even if there are threads trying to
- * acquire the lock but have not yet done so. This method is
- * designed to facilitate construction of subclasses that provide
- * more extensive lock monitoring facilities.
- * @return the owner, or <tt>null</tt> if not owned.
+ * Returns the thread that currently owns the write lock, or
+ * {@code null} if not owned. When this method is called by a
+ * thread that is not the owner, the return value reflects a
+ * best-effort approximation of current lock status. For example,
+ * the owner may be momentarily {@code null} even if there are
+ * threads trying to acquire the lock but have not yet done so.
+ * This method is designed to facilitate construction of
+ * subclasses that provide more extensive lock monitoring
+ * facilities.
+ *
+ * @return the owner, or {@code null} if not owned
*/
protected Thread getOwner() {
return sync.getOwner();
}
-
+
/**
* Queries the number of read locks held for this lock. This
* method is designed for use in monitoring system state, not for
@@ -916,17 +1205,19 @@
* Queries if the write lock is held by any thread. This method is
* designed for use in monitoring system state, not for
* synchronization control.
- * @return <tt>true</tt> if any thread holds write lock and
- * <tt>false</tt> otherwise.
+ *
+ * @return {@code true} if any thread holds the write lock and
+ * {@code false} otherwise
*/
public boolean isWriteLocked() {
return sync.isWriteLocked();
}
/**
- * Queries if the write lock is held by the current thread.
- * @return <tt>true</tt> if current thread holds this lock and
- * <tt>false</tt> otherwise.
+ * Queries if the write lock is held by the current thread.
+ *
+ * @return {@code true} if the current thread holds the write lock and
+ * {@code false} otherwise
*/
public boolean isWriteLockedByCurrentThread() {
return sync.isHeldExclusively();
@@ -937,8 +1228,8 @@
* current thread. A writer thread has a hold on a lock for
* each lock action that is not matched by an unlock action.
*
- * @return the number of holds on this lock by the current thread,
- * or zero if this lock is not held by the current thread.
+ * @return the number of holds on the write lock by the current thread,
+ * or zero if the write lock is not held by the current thread
*/
public int getWriteHoldCount() {
return sync.getWriteHoldCount();
@@ -952,6 +1243,7 @@
* returned collection are in no particular order. This method is
* designed to facilitate construction of subclasses that provide
* more extensive lock monitoring facilities.
+ *
* @return the collection of threads
*/
protected Collection<Thread> getQueuedWriterThreads() {
@@ -966,6 +1258,7 @@
* returned collection are in no particular order. This method is
* designed to facilitate construction of subclasses that provide
* more extensive lock monitoring facilities.
+ *
* @return the collection of threads
*/
protected Collection<Thread> getQueuedReaderThreads() {
@@ -973,41 +1266,42 @@
}
/**
- * Queries whether any threads are waiting to acquire. Note that
- * because cancellations may occur at any time, a <tt>true</tt>
- * return does not guarantee that any other thread will ever
- * acquire. This method is designed primarily for use in
- * monitoring of the system state.
+ * Queries whether any threads are waiting to acquire the read or
+ * write lock. Note that because cancellations may occur at any
+ * time, a {@code true} return does not guarantee that any other
+ * thread will ever acquire a lock. This method is designed
+ * primarily for use in monitoring of the system state.
*
- * @return true if there may be other threads waiting to acquire
- * the lock.
+ * @return {@code true} if there may be other threads waiting to
+ * acquire the lock
*/
- public final boolean hasQueuedThreads() {
+ public final boolean hasQueuedThreads() {
return sync.hasQueuedThreads();
}
/**
- * Queries whether the given thread is waiting to acquire this
- * lock. Note that because cancellations may occur at any time, a
- * <tt>true</tt> return does not guarantee that this thread
- * will ever acquire. This method is designed primarily for use
- * in monitoring of the system state.
+ * Queries whether the given thread is waiting to acquire either
+ * the read or write lock. Note that because cancellations may
+ * occur at any time, a {@code true} return does not guarantee
+ * that this thread will ever acquire a lock. This method is
+ * designed primarily for use in monitoring of the system state.
*
* @param thread the thread
- * @return true if the given thread is queued waiting for this lock.
- * @throws NullPointerException if thread is null
+ * @return {@code true} if the given thread is queued waiting for this lock
+ * @throws NullPointerException if the thread is null
*/
- public final boolean hasQueuedThread(Thread thread) {
+ public final boolean hasQueuedThread(Thread thread) {
return sync.isQueued(thread);
}
/**
- * Returns an estimate of the number of threads waiting to
- * acquire. The value is only an estimate because the number of
- * threads may change dynamically while this method traverses
- * internal data structures. This method is designed for use in
- * monitoring of the system state, not for synchronization
- * control.
+ * Returns an estimate of the number of threads waiting to acquire
+ * either the read or write lock. The value is only an estimate
+ * because the number of threads may change dynamically while this
+ * method traverses internal data structures. This method is
+ * designed for use in monitoring of the system state, not for
+ * synchronization control.
+ *
* @return the estimated number of threads waiting for this lock
*/
public final int getQueueLength() {
@@ -1016,12 +1310,13 @@
/**
* Returns a collection containing threads that may be waiting to
- * acquire. Because the actual set of threads may change
- * dynamically while constructing this result, the returned
- * collection is only a best-effort estimate. The elements of the
- * returned collection are in no particular order. This method is
- * designed to facilitate construction of subclasses that provide
- * more extensive monitoring facilities.
+ * acquire either the read or write lock. Because the actual set
+ * of threads may change dynamically while constructing this
+ * result, the returned collection is only a best-effort estimate.
+ * The elements of the returned collection are in no particular
+ * order. This method is designed to facilitate construction of
+ * subclasses that provide more extensive monitoring facilities.
+ *
* @return the collection of threads
*/
protected Collection<Thread> getQueuedThreads() {
@@ -1031,18 +1326,18 @@
/**
* Queries whether any threads are waiting on the given condition
* associated with the write lock. Note that because timeouts and
- * interrupts may occur at any time, a <tt>true</tt> return does
- * not guarantee that a future <tt>signal</tt> will awaken any
+ * interrupts may occur at any time, a {@code true} return does
+ * not guarantee that a future {@code signal} will awaken any
* threads. This method is designed primarily for use in
* monitoring of the system state.
+ *
* @param condition the condition
- * @return <tt>true</tt> if there are any waiting threads.
- * @throws IllegalMonitorStateException if this lock
- * is not held
+ * @return {@code true} if there are any waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
* @throws IllegalArgumentException if the given condition is
- * not associated with this lock
- * @throws NullPointerException if condition null
- */
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
public boolean hasWaiters(Condition condition) {
if (condition == null)
throw new NullPointerException();
@@ -1058,14 +1353,14 @@
* serves only as an upper bound on the actual number of waiters.
* This method is designed for use in monitoring of the system
* state, not for synchronization control.
+ *
* @param condition the condition
- * @return the estimated number of waiting threads.
- * @throws IllegalMonitorStateException if this lock
- * is not held
+ * @return the estimated number of waiting threads
+ * @throws IllegalMonitorStateException if this lock is not held
* @throws IllegalArgumentException if the given condition is
- * not associated with this lock
- * @throws NullPointerException if condition null
- */
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
+ */
public int getWaitQueueLength(Condition condition) {
if (condition == null)
throw new NullPointerException();
@@ -1083,13 +1378,13 @@
* are in no particular order. This method is designed to
* facilitate construction of subclasses that provide more
* extensive condition monitoring facilities.
+ *
* @param condition the condition
* @return the collection of threads
- * @throws IllegalMonitorStateException if this lock
- * is not held
+ * @throws IllegalMonitorStateException if this lock is not held
* @throws IllegalArgumentException if the given condition is
- * not associated with this lock
- * @throws NullPointerException if condition null
+ * not associated with this lock
+ * @throws NullPointerException if the condition is null
*/
protected Collection<Thread> getWaitingThreads(Condition condition) {
if (condition == null)
@@ -1101,18 +1396,19 @@
/**
* Returns a string identifying this lock, as well as its lock state.
- * The state, in brackets, includes the String "Write locks ="
- * follwed by the number of reentrantly held write locks, and the
- * String "Read locks =" followed by the number of held
+ * The state, in brackets, includes the String {@code "Write locks ="}
+ * followed by the number of reentrantly held write locks, and the
+ * String {@code "Read locks ="} followed by the number of held
* read locks.
- * @return a string identifying this lock, as well as its lock state.
+ *
+ * @return a string identifying this lock, as well as its lock state
*/
public String toString() {
int c = sync.getCount();
- int w = exclusiveCount(c);
- int r = sharedCount(c);
-
- return super.toString() +
+ int w = Sync.exclusiveCount(c);
+ int r = Sync.sharedCount(c);
+
+ return super.toString() +
"[Write locks = " + w + ", Read locks = " + r + "]";
}
Added: harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package-info.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package-info.java?rev=794678&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package-info.java (added)
+++ harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package-info.java Thu Jul 16 14:01:15 2009
@@ -0,0 +1,47 @@
+/*
+ * Written by Doug Lea with assistance from members of JCP JSR-166
+ * Expert Group and released to the public domain, as explained at
+ * http://creativecommons.org/licenses/publicdomain
+ */
+
+/**
+ * Interfaces and classes providing a framework for locking and waiting
+ * for conditions that is distinct from built-in synchronization and
+ * monitors. The framework permits much greater flexibility in the use of
+ * locks and conditions, at the expense of more awkward syntax.
+ *
+ * <p>The {@link java.util.concurrent.locks.Lock} interface supports
+ * locking disciplines that differ in semantics (reentrant, fair, etc),
+ * and that can be used in non-block-structured contexts including
+ * hand-over-hand and lock reordering algorithms. The main implementation
+ * is {@link java.util.concurrent.locks.ReentrantLock}.
+ *
+ * <p>The {@link java.util.concurrent.locks.ReadWriteLock} interface
+ * similarly defines locks that may be shared among readers but are
+ * exclusive to writers. Only a single implementation, {@link
+ * java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
+ * it covers most standard usage contexts. But programmers may create
+ * their own implementations to cover nonstandard requirements.
+ *
+ * <p>The {@link java.util.concurrent.locks.Condition} interface
+ * describes condition variables that may be associated with Locks.
+ * These are similar in usage to the implicit monitors accessed using
+ * {@code Object.wait}, but offer extended capabilities.
+ * In particular, multiple {@code Condition} objects may be associated
+ * with a single {@code Lock}. To avoid compatibility issues, the
+ * names of {@code Condition} methods are different from the
+ * corresponding {@code Object} versions.
+ *
+ * <p>The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
+ * class serves as a useful superclass for defining locks and other
+ * synchronizers that rely on queuing blocked threads. The {@link
+ * java.util.concurrent.locks.AbstractQueuedLongSynchronizer} class
+ * provides the same functionality but extends support to 64 bits of
+ * synchronization state. The {@link java.util.concurrent.locks.LockSupport}
+ * class provides lower-level blocking and unblocking support that is
+ * useful for those developers implementing their own customized lock
+ * classes.
+ *
+ * @since 1.5
+ */
+package java.util.concurrent.locks;
Propchange: harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package-info.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html?rev=794678&r1=794677&r2=794678&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html (original)
+++ harmony/enhanced/classlib/trunk/modules/concurrent/src/main/java/java/util/concurrent/locks/package.html Thu Jul 16 14:01:15 2009
@@ -1,44 +0,0 @@
-<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
-<html> <head>
-<title>Locks</title>
-</head>
-
-<body>
-
-Interfaces and classes providing a framework for locking and waiting
-for conditions that is distinct from built-in synchronization and
-monitors. The framework permits much greater flexibility in the use of
-locks and conditions, at the expense of more awkward syntax.
-
-<p> The {@link java.util.concurrent.locks.Lock} interface supports
-locking disciplines that differ in semantics (reentrant, fair, etc),
-and that can be used in non-block-structured contexts including
-hand-over-hand and lock reordering algorithms. The main implementation
-is {@link java.util.concurrent.locks.ReentrantLock}.
-
-<p> The {@link java.util.concurrent.locks.ReadWriteLock} interface
-similarly defines locks that may be shared among readers but are
-exclusive to writers. Only a single implementation, {@link
-java.util.concurrent.locks.ReentrantReadWriteLock}, is provided, since
-it covers most standard usage contexts. But programmers may create
-their own implementations to cover nonstandard requirements.
-
-<p> The {@link java.util.concurrent.locks.Condition} interface
-describes condition variables that may be associated with Locks.
-These are similar in usage to the implicit monitors accessed using
-<tt>Object.wait</tt>, but offer extended capabilities. In particular,
-multiple <tt>Condition</tt> objects may be associated with a single
-<tt>Lock</tt>. To avoid compatibility issues, the names of
-<tt>Condition</tt> methods are different than the corresponding
-<tt>Object</tt> versions.
-
-<p> The {@link java.util.concurrent.locks.AbstractQueuedSynchronizer}
-class serves as a useful superclass for defining locks and other
-synchronizers that rely on queuing blocked threads. The {@link
-java.util.concurrent.locks.LockSupport} class provides lower-level
-blocking and unblocking support that is useful for those developers
-implementing their own customized lock classes.
-
-@since 1.5
-
-</body> </html>