ReentrantReadWriteLock中,为什么在获取写锁前要释放读锁,查的说会产生死锁,不太明白
来源:6-6 J.U.C之AQS-ReentrantLock与锁-2
茶铺里的水
2018-03-29
* class CachedData {
* Object data;
* volatile boolean cacheValid;
* final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
*
* void processCachedData() {
* rwl.readLock().lock();
* if (!cacheValid) {
* // Must release read lock before acquiring write lock
* rwl.readLock().unlock();
* rwl.writeLock().lock();
* try {
* // 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
* rwl.readLock().lock();
* } finally {
* rwl.writeLock().unlock(); // Unlock write, still hold read
* }
* }
*
* try {
* use(data);
* } finally {
* rwl.readLock().unlock();
* }
* }
* }}写回答
1回答
-
你好,Reentrant代表重入,字面意思这是一个可重入的读写锁。这里的读写锁都可重入, 线程可同时具有读写锁。
获取 writeLock 时 一定是在没有线程获取 readLock 或 writeLock 时才获取成功,取 readLock 的过程中, 若此时有线程已获取写锁 或 同步等待队列 里面有获取 writeLock 的线程, 则一定会等待获取writeLock成功并释放或放弃获取 后才能获取(死锁时, 已获取 readLock 的线程还能重复获取 readLock)
基于上面的特性,我们再来说死锁的问题:
线程A获取 readLock 成功,然后开始获取 writeLock, 这时发现 readLock 已经 readLock 已经被线程获取, 且writeLock没有被人获取(方法 tryAcquire c != 0 && w == 0), 直接加入到同步等待队列 里面, 并且一直等待 readLock 的释放(等待自己readLock释放, 其实是不可能的)
线程B之后第一次获取 readLock, 此时同步等待队列里面有等待的节点, 就在那一直等待。
死锁就出现了。
112018-03-29
相似问题