java.lang.Objectjava.util.concurrent.locks.ReentrantReadWriteLock
An implementation of ReadWriteLock
supporting similar
semantics to ReentrantLock
.
This class has the following properties:
This class does not impose a reader or writer preference ordering for lock access. However, it does support an optional fairness 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.
This lock allows both readers and writers to reacquire read or
write locks in the style of a ReentrantLock
. Readers are not
allowed until all write locks held by the writing thread have been
released.
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.
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 not possible.
The read lock and write lock both support interruption during lock acquisition. And both view the interruptible lock methods as explicit interruption points and give preference to responding to the interrupt over normal or reentrant acquisition of the lock, or over reporting the elapse of the waiting time, as applicable.
Condition
support
The write lock provides a Condition
implementation that
behaves in the same way, with respect to the write lock, as the
Condition
implementation provided by
ReentrantLock.newCondition()
does for ReentrantLock
.
This Condition
can, of course, only be used with the write lock.
The read lock does not support a Condition
and
readLock().newCondition() throws
UnsupportedOperationException.
Sample usage. Here is a code sketch showing how to exploit reentrancy to perform lock downgrading after updating a cache (exception handling is elided for simplicity):
class CachedData { Object data; volatile boolean cacheValid; ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); void processCachedData() { rwl.readLock().lock(); if (!cacheValid) { // upgrade lock manually rwl.readLock().unlock(); // must unlock first to obtain writelock rwl.writeLock().lock(); if (!cacheValid) { // recheck data = ... cacheValid = true; } // 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(); } }
In addition to the above, this reference implementation has the following property:
While not exposing a means to query the owner, the write lock does internally define an owner and so the write lock can only be released by the thread that acquired it.
In contrast, the read lock has no concept of ownership. Consequently, while not a particularly good practice, it is possible to acquire a read lock in one thread, and release it in another. This can occasionally be useful.
Nested Class Summary | |
---|---|
static class |
ReentrantReadWriteLock.WriterConditionObject
Condition implementation for use with ReentrantReadWriteLock. |
Constructor Summary | |
---|---|
ReentrantReadWriteLock()
Creates a new ReentrantReadWriteLock with default ordering properties. |
|
ReentrantReadWriteLock(boolean fair)
Creates a new ReentrantReadWriteLock with the given fairness policy. |
Method Summary | |
---|---|
protected Collection<Thread> |
getQueuedReaderThreads()
Returns a collection containing threads that may be waiting to acquire the read lock. |
protected Collection<Thread> |
getQueuedThreads()
Returns a collection containing threads that may be waiting to acquire this lock. |
protected Collection<Thread> |
getQueuedWriterThreads()
Returns a collection containing threads that may be waiting to acquire the write lock. |
int |
getQueueLength()
Returns an estimate of the number of threads waiting to acquire this lock. |
int |
getReadLocks()
Queries the number of read locks held for this lock. |
int |
getWriteHoldCount()
Queries the number of reentrant write holds on this lock by the current thread. |
protected Thread |
getWriter()
Returns the thread that currently owns the write lock, or null if not owned. |
boolean |
isFair()
Return true if this lock has fairness set true. |
boolean |
isWriteLocked()
Queries if the write lock is held by any thread. |
boolean |
isWriteLockedByCurrentThread()
Queries if the write lock is held by the current thread. |
Lock |
readLock()
Return the lock used for reading. |
Lock |
writeLock()
Return the lock used for writing. |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Constructor Detail |
---|
public ReentrantReadWriteLock()
public ReentrantReadWriteLock(boolean fair)
fair
- true if this lock should use a fair ordering policyMethod Detail |
---|
public Lock writeLock()
ReadWriteLock
writeLock
in interface ReadWriteLock
public Lock readLock()
ReadWriteLock
readLock
in interface ReadWriteLock
public boolean isFair()
public int getReadLocks()
public boolean isWriteLocked()
public boolean isWriteLockedByCurrentThread()
public int getWriteHoldCount()
A writer thread has a hold on a lock for each lock action that is not matched by an unlock action.
public int getQueueLength()
protected Thread getWriter()
protected Collection<Thread> getQueuedThreads()
protected Collection<Thread> getQueuedWriterThreads()
protected Collection<Thread> getQueuedReaderThreads()