请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

ReentrantReadWriteLock中,为什么在获取写锁前要释放读锁,查的说会产生死锁,不太明白

* 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回答

Jimin 2018-03-29 16:12:32

你好,Reentrant代表重入,字面意思这是一个可重入的读写锁。这里的读写锁都可重入, 线程可同时具有读写锁。

获取 writeLock 时 一定是在没有线程获取 readLock 或 writeLock 时才获取成功,取 readLock 的过程中, 若此时有线程已获取写锁 或 同步等待队列 里面有获取 writeLock 的线程, 则一定会等待获取writeLock成功并释放或放弃获取 后才能获取(死锁时, 已获取 readLock 的线程还能重复获取 readLock)

基于上面的特性,我们再来说死锁的问题:

线程A获取 readLock 成功,然后开始获取 writeLock, 这时发现 readLock 已经 readLock 已经被线程获取, 且writeLock没有被人获取(方法 tryAcquire c != 0 && w == 0), 直接加入到同步等待队列 里面, 并且一直等待 readLock 的释放(等待自己readLock释放, 其实是不可能的)

线程B之后第一次获取 readLock, 此时同步等待队列里面有等待的节点, 就在那一直等待。

死锁就出现了。

1 回复 有任何疑惑可以回复我~
  • 提问者 茶铺里的水 #1
    谢谢老师,解答非常详细!!!
    回复 有任何疑惑可以回复我~ 2018-03-29 16:21:27
问题已解决,确定采纳
还有疑问,暂不采纳
意见反馈 帮助中心 APP下载
官方微信