我现在在我的代码中使用ReentrantReadWriteLock来同步对树状结构的访问.这个结构很大,并且很多线程一次读取,偶尔会对它的一小部分进行修改 - 所以它似乎很适合读写习惯用法.我理解,对于这个特定的类,不能将读锁提升到写锁,因此根据Javadoc,必须在获得写锁之前释放读锁.我以前在非重入上下文中成功使用了这种模式.
然而,我发现我无法永久地阻止写入锁定.由于读锁是可重入的,我实际上正在使用它,简单的代码
lock.getReadLock().unlock();
lock.getWriteLock().lock()Run Code Online (Sandbox Code Playgroud)
如果我已经重新获得了重新锁定,则可以阻止.每次解锁调用只会减少保持计数,并且仅在保持计数达到零时才实际释放锁定.
编辑澄清这一点,因为我认为我最初没有解释得太清楚 - 我知道这个类中没有内置的锁升级,我必须简单地释放读锁并获得写锁.我的问题是,无论其他线程正在做什么,如果它重新获取它,调用getReadLock().unlock()可能实际上不会释放此线程对锁定的保持,在这种情况下,调用getWriteLock().lock()将永远阻塞,因为此线程仍然保持读取锁定,从而阻止自己.
例如,即使在没有其他线程访问锁的情况下运行单线程时,此代码段也永远不会到达println语句:
final ReadWriteLock lock = new ReentrantReadWriteLock();
lock.getReadLock().lock();
// In real code we would go call other methods that end up calling back and
// thus locking again
lock.getReadLock().lock();
// Now we do some stuff and realise we need to write so try to escalate the
// lock as per the Javadocs and the above description
lock.getReadLock().unlock(); // Does not actually …Run Code Online (Sandbox Code Playgroud)