从ReentrantReadWriteLock class javadoc
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// Must release read lock before acquiring write lock
5: rwl.readLock().unlock();
6: rwl.writeLock().lock();
// 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
14: rwl.readLock().lock();
15: rwl.writeLock().unlock(); // Unlock write, still hold read
}
use(data);
rwl.readLock().unlock();
}为什么我们必须在获取评论中所写的写锁之前释放读锁?如果当前线程持有读锁,则应允许它在其他线程不再读取时获取写锁,而不管当前线程是否也持有读锁。这是我所期望的行为。
我预计第5行和第6行的锁升级和第14行和第15行的锁降级将在ReentrantReadWriteLock类内部完成。为什么这不可能呢?
换句话说,我希望代码能像这样正常工作:
void processCachedData() {
rwl.readLock().lock();
if (!cacheValid) {
// The readlock is upgraded to writeLock when other threads
// release their readlocks.
rwl.writeLock().lock();
// no need to recheck: other threads can't have acquired
// the write lock since this thread still holds also the readLock!!!
if (!cacheValid) {
data = ...
cacheValid = true;
}
// Downgrade by acquiring read lock before releasing write lock
rwl.writeLock().unlock(); // Unlock write, still hold read
}
use(data);
rwl.readLock().unlock();
}这看起来是一种更好、更安全的处理锁定的方法,不是吗?
有人能解释一下这个奇怪的实现的原因吗?谢谢。
发布于 2013-06-04 00:49:08
将读锁升级为写锁的问题是,如果两个线程同时尝试这样做,可能会导致死锁。请考虑以下顺序:
现在出现了一个死锁。线程A和线程B都不能继续,也不会释放读锁。
发布于 2013-06-04 00:49:52
Javadoc明确声明将读锁升级为写锁是不可能的。这样做的原因是因为它会造成死锁。
两个线程现在都在等待对方...永远不变。
发布于 2013-06-04 00:43:19
可重入性允许从写锁降级为读锁,方法是先获取写锁,然后获取读锁,然后释放写锁。但是,从读锁升级到写锁是不可能的(这会导致死锁)。
来源:http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/ReentrantReadWriteLock.html
https://stackoverflow.com/questions/16901640
复制相似问题