ReadWriteLock
downgrade is allowed by ReentrantReadWriteLock
implementation (tryLock()
from the example below always returns true
):
void downgrade(final ReadWriteLock readWriteLock) {
boolean downgraded = false;
readWriteLock.writeLock().lock();
try {
// Always true, as we already hold a W lock.
final boolean readLockAcquired = readWriteLock.readLock().tryLock();
if (readLockAcquired) {
// Now holding both a R and a W lock.
assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 1;
assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 1;
readWriteLock.writeLock().unlock();
downgraded = true;
try {
// Now do some work with only a R lock held
} finally {
readWriteLock.readLock().unlock();
assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 0;
assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 0;
}
}
} finally {
if (!downgraded) {
// Never (we were holding a W lock while trying a R lock).
readWriteLock.writeLock().unlock();
}
assert ((ReentrantReadWriteLock) readWriteLock).getReadHoldCount() == 0;
assert ((ReentrantReadWriteLock) readWriteLock).getWriteHoldCount() == 0;
}
}
What was the idea behind not allowing a lock upgrade in a similar manner? The tryLock()
method for a Write lock below could safely return true
w/o a risk for a deadlock in the absence of other threads holding a Read lock:
void upgrade(final ReadWriteLock readWriteLock) {
readWriteLock.readLock().lock();
try {
// Always false: lock upgrade is not allowed
final boolean writeLockAcquired = readWriteLock.writeLock().tryLock();
// ...
} finally {
readWriteLock.readLock().unlock();
}
}