前言
这篇文章是我自己整理前面几篇关于ReentrantLock和Condition的文章:
常见并发工具的使用和原理解析——Condition(重点在第五节)
因这几篇文章以及讲的挺详细了,所以本篇文章只做总结和捋思路,不涉及太详细的源码解读。
一、ReentratLock
1.1 ReentratLock类关系图
- ReentrantLock实现了Lock接口
- ReentrantLock依赖Sync类——Sync类是 ReentrantLock类的一个属性
- Sync类是AbstractQueuedSynchronizer(AQS)的子类
- 而ReentrantLock实际用到了Sync的两个子类FairSync和NonFairSync
1.2 什么是重入锁、读写锁
重入锁:线程获取了锁之后,再次获取锁,不需要阻塞,而是直接增加一次state计数。
读写锁:ReentrantReadWriteLock——重入读写锁,实现了ReadWriteLock接口。
读写锁特性:实用读多写少的情况
- 读与读不互斥
- 读与写互斥
- 写与写互斥
1.3 AQS概览
- state——volatile修饰
- exclusiveOwnerThread——当前占有锁的线程
- Node——节点,包装Thread
waitStatus——节点状态,具体有哪几种可以自行了解
1.4 ReentrantLock非公平锁获取锁的逻辑
ReentrantLock#lock:
接下来看AbstractQueuedSynchronizer#acquire方法:
继续看ReentratLock.NonFairSync#nonfairTryAcquire方法:
AbstractQueuedSynchronizer#acquireQueued方法:
AbstractQueuedSynchronizer#shouldParkAfterFailedAcquire方法:
1.5 ReentrantLock非公平锁释放锁的逻辑
二、Condition
Condition的作用是线程间的协作,替代Object.wait()和notify()。他是属于AQS的内部类,名字叫等待队列,主要是两个方法:
- await():释放锁,并将自己挂起,等待唤醒
- signal():唤醒其他线程
Condition必须配合Lock才能使用,包括Condition对象也是通过Lock.newCondition()方法新建出来的。
等待队列图示:
新增的节点会添加到队尾。
2.1 await()方法
2.2 signal()方法
signal()和await()方法一样,也是抢到锁后才能执行的。
疑问:
为什么③中需要判断前一个节点状态,以及cas替换前一个节点状态为Signal?