Safely downgrading a write lock with ReadWriteLock
2010, Feb 23
A simple pattern to safely downgrade a write lock to a read lock safely.
A simple pattern to downgrade a write lock to a read lock safely:
ReadWriteLock rwl = getLock();
Lock lock = rwl.writeLock();
lock.lock();
try {
// <<... Perform write operation ...>>
// downgrade lock safely
final Lock readLock = rwl.readLock();
readLock.lock(); // Possible failure #1
try {
lock.unlock(); // Possible failure #2
} finally {
lock = readLock;
}
} finally {
lock.unlock();
}
The reason this works is as follows:
- Anything which fails before possible failure #1 will cause the original lock to unlock, due to the
finallyblock. - If possible failure #1 occurs, the read lock is never locked, thus the write lock is still unlocked in the outer
finallyblock. - If possible failure #2 occurs, the now-locked read lock is stashed into
lockthanks to the innerfinallyblock, thus the read lock is released in the outerfinallyblock. At this point, no matter what, the write lock is released. - Any failure after possible failure #2 will cause the outer
finallyblock to release the read lock.
The nice thing about this approach is that you can even downgrade the lock inside of a conditional and the structure is not broken.