AQS原理
1. 概述
1)AbstractQueuedSynchronizer
用来构建锁或者其它同步器组件的重量级基础框架, 通过内置的FIFO队列来完成资源获取线程的排队工作,并通过一个int变量表示持有锁的状态
2)特点:
用 state 属性来表示资源的状态(分独占模式和共享模式),子类需要定义如何维护这个状态,控制如何获取锁和释放锁
getState - 获取 state 状态
setState - 设置 state 状态
compareAndSetState - cas 机制设置 state 状态
独占模式是只有一个线程能够访问资源,而共享模式可以允许多个线程访问资源
提供了基于 FIFO 的等待队列,类似于 Monitor 的 EntryList
条件变量来实现等待、唤醒机制,支持多个条件变量,类似于 Monitor 的 WaitSet
3)子类主要实现这样一些方法(默认抛出 UnsupportedOperationException)
tryAcquire
tryRelease
tryAcquireShared
tryReleaseShared
isHeldExclusively
2、应用
java.util.concurrent包中很多类都依赖于这个类所提供队列式同步器,比如说常用的ReentranLock,Semaphore和CountDownLatch等
3、原理图解
state变量+CLH双端Node队列
AQS使用一个volatile的int类型的成员变量来表示同步状态,通过内置的 FIFO队列来完成资源获取的排队工作将每条要去抢占资源的线程封装成 一个Node节点来实现锁的分配,通过CAS完成对State值的修改。
·lock
1)A顾客来的时候窗口为空(state=0),直接抢占
2)B顾客来的时候有人,先尝试抢一下,失败后开始入队
3)入队时先生成一个哨兵节点(thread=null),然后修改头尾前后四个指针,B就编程了队尾
4)B不安分再次自选获取窗口,失败后就会真正入队(被park)
5)C顾客来和B的流程类似,完成入队
+++++++++++
·unluck
1)A执行完之后,窗口空出,state改为0可用
2)唤醒B,B就进窗口办理业务
(这里非公平锁的话,有其他未入队的线程可能抢先,但是队列内的顺序已经固定,先进先出)
3)修改B原先节点的Thread=null,修改指针,B节点代替之前的哨兵成为哨兵头节点
4)原哨兵节点无指向,会被回收(工具人o(╥﹏╥)o)
4、源码方法脉络
详见 https://cmysz.blog.youkuaiyun.com/article/details/109704701