tryAcquireShared
exclusiveCount(state)!=0&&getExclusiveOwnerThread!=current//如果现在是写锁状态,并且当前线程不是拥有锁的线程
也就是如果是当前线程是拥有写锁的,读操作也可以进去
if(!readShouldBlock(current)&&CAS(state, state+SHARED_UNIT)){
cacheHoldCounter.count++ //重入计数
return 1;
}
return -1;
tryAcquire
if(state!=0) {
if(exclusiveCount==0||current != getExclusiveOwnerThread)//因为状态大于0,但如果写的部分为零,说明只有读锁,那么写锁肯定进不去。
return false;
}
if(writeShouldBlock(current)||!CAS(c,c+acquires)) {
return false;
}
setExclusiveOwnerThread(current)
return ture
释放独占锁
nextc = state-release
if(exclusiveCount(nextc)==0) { //判断低四位的值是否为0,表示写锁重入的次数
setExclusiveOwnerThread(null)
setState(nextc)
return true
} else { //表示还有部分锁的重入没解开,所以返回false,不让AQS去唤醒后面的节点
setState(nextc)
return false
}
如果为true 将会执行
unparkSuccessor(h)
释放共享锁
if(cacheHoldCounter.tryDecrement()<=0) throw new IllegalMonitorStateException //用holdCounter表示重入次数
for(;;) {
if(CAS(state, state-SHARE_UNIT)) //state高四位减去一
return nextc==0 //如果不等于0表示还有部分锁的重入没解开,返回false,不让AQS去唤醒后面的节点
}
如果为true,将会执行
doReleaseShared()
FairSync
readerShouldBlock(current)//判断current != head.next.thread
NonfairSync
readerShouldBlock(current)//判断head.next.nextWaiter != Node.SHARED
总结:ReentrantReadWriteLock比较有意思的几个地方
1、queue里面两种节点:独占和共享。独占节点唤醒之后,会移除当前节点并继续执行;共享节点唤醒之后,会移除当前节点并扩散后面的共享节点
2、对state的巧妙设计,高四位用来表示读锁状态,低四位表示写锁状态。
3、对某个线程读锁的重入,用AQS现有的结果无法满足,所以就依靠了ThreadLocal来保存某个线程对某个锁的持有情况和重入数量。
互斥锁是可以用一个state变量来表示锁的重入情况,因为只对应一个线程,完全可以在获取和释放前做current==getExclusiveOwnerThread来判断
分享到:
相关推荐
6.JUC并发工具类在大厂的应用场景详解 (1).pdf ...8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
针对这种场景,JAVA的并发包提供了读写锁ReentrantReadWriteLock,它表示两个锁,一个是读操作相关的锁,称为共享锁;一个是写相关的锁,称为排他锁 类图如下: 说明:如上图所示Sync为ReentrantReadWriteLock...
读写锁是将被锁保护的临界资源的读操作和写操作分开,允许同时有多个线程同时对临界资源进行读操作,任意时刻只允许一个线程对资源进行写操作。简单的说,对与读操作采用的是 共享锁 ,对于写操作采用的是 排他锁...
6.JUC并发工具类在大厂的应用场景详解 (1).pdf ...8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
6.JUC并发工具类在大厂的应用场景详解 (1).pdf ...8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
6.JUC并发工具类在大厂的应用场景详解 (1).pdf ...8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
6.JUC并发工具类在大厂的应用场景详解 (1).pdf ...8、读写锁ReentrantReadWriteLock&StampLock详解.pdf 9、并发容器 (Map、List、Set) 实战及其原理.pdf 10、阻塞队列BlockingQueue 实战及其原理分析.pdf
细读ReentrantReadWriteLock源码.mp4 ReentrantReadWriteLock锁降级详解.mp4 线程安全性问题简单总结.mp4 线程之间的通信之wait notify.mp4 通过生产者消费者模型理解等待唤醒机制.mp4 Condition的使用及原理解析....
11.深入理解读写锁ReentrantReadWriteLock 12.详解Condition的await和signal等待通知机制 13.LockSupport工具 14.并发容器之ConcurrentHashMap(JDK 1.8版本) 15.并发容器之ConcurrentLinkedQueue 16.并发容器之...
第26节细读ReentrantReadWriteLock源码00:30:38分钟 | 第27节ReentrantReadWriteLock锁降级详解00:13:32分钟 | 第28节线程安全性问题简单总结00:15:34分钟 | 第29节线程之间的通信之wait/notify00:32:12分钟 | ...
第26节细读ReentrantReadWriteLock源码00:30:38分钟 | 第27节ReentrantReadWriteLock锁降级详解00:13:32分钟 | 第28节线程安全性问题简单总结00:15:34分钟 | 第29节线程之间的通信之wait/notify00:32:12分钟 | ...
第26节细读ReentrantReadWriteLock源码00:30:38分钟 | 第27节ReentrantReadWriteLock锁降级详解00:13:32分钟 | 第28节线程安全性问题简单总结00:15:34分钟 | 第29节线程之间的通信之wait/notify00:32:12分钟 | ...
第26节细读ReentrantReadWriteLock源码00:30:38分钟 | 第27节ReentrantReadWriteLock锁降级详解00:13:32分钟 | 第28节线程安全性问题简单总结00:15:34分钟 | 第29节线程之间的通信之wait/notify00:32:12分钟 | ...
* 使用 **ReenTrantReadWriteLock** 降低同一文件读写冲突,提高文件IO并发度 ### 模块说明: **Client:** 与应用直接交互的服务,提供文件操作相关接口 **Meta:** 维持文件元数据,统一管理chunk信息 **chunk-...
│ 高并发编程第二阶段17讲、多线程读写锁分离设计模式讲解-中.mp4 │ 高并发编程第二阶段18讲、多线程读写锁分离设计模式讲解-下.mp4 │ 高并发编程第二阶段19讲、多线程不可变对象设计模式Immutable-上.mp4 │...
│ 高并发编程第二阶段17讲、多线程读写锁分离设计模式讲解-中.mp4 │ 高并发编程第二阶段18讲、多线程读写锁分离设计模式讲解-下.mp4 │ 高并发编程第二阶段19讲、多线程不可变对象设计模式Immutable-上.mp4 │...