AQS
1、AQS的作用
AQS 是一个用于构建锁、同步器等线程协作工具类的框架,有了 AQS 以后,很多用于线程协作的工具类就都可以很方便的被写出来,有了 AQS 之后,可以让更上层的开发极大的减少工作量,避免重复造轮子,同时也避免了上层因处理不当而导致的线程安全问题,因为 AQS 把这些事情都做好了。
2、AQS内部原理
AQS 最核心的三大部分就是状态、队列和期望协作工具类去实现的获取/释放等重要方法
state 状态
/**
* The synchronization state.
*/
private volatile int state;
state的含义不是固定不变的,由具体的实现来定义
比如,在 CountDownLatch 工具类里面,state 表示的是需要“倒数”的数量。一开始我们假设把它设置为 5,当每次调用 CountDown 方法时,state 就会减 1,一直减到 0 的时候就代表这个门闩被放开。
state 在 ReentrantLock 中表示的是锁的占有情况。最开始是 0,表示没有任何线程占有锁;如果 state 变成 1,则就代表这个锁已经被某一个线程所持有了。
因为 ReentrantLock 是可重入的,同一个线程可以再次拥有这把锁就叫重入。 state 就会逐渐的往上加,state 的值表示重入的次数。每释放一次就会减一每重入一次就会加一。
我们举两个和 state 相关的方法,分别是 compareAndSetState 及 setState
// Unsafe 里面的 CAS 操作,利用 CPU 指令的原子性保证了这个操作的原子性
protected final boolean compareAndSetState(int expect, int update) {
return unsafe.compareAndSwapInt(this, stateOffset, expect, update);
}
//state为volatile修饰变量 又是基本数据类型所以直接赋值线程安全
protected final void setState(int newState) {
state = newState;
}
FIFO 队列
AQS 的第二个核心部分,FIFO 队列,即先进先出队列,这个队列最主要的作用是存储等待的线程。假设很多线程都想要同时抢锁,那么大部分的线程是抢不到的,就得需要有一个队列来存放。所以 AQS 的一大功能就是充当线程的“排队管理器”。
获取/释放方法
AQS 的第三个核心部分,获取/释放方法。这些方法是协作工具类的逻辑的具体体现,需要每一个协