AQS的全称为(AbstractQueuedSynchronizer)抽象的队列同步器,是一个用来构建锁和同步器的框架,使用AQS能简单且高效地构造出应用广泛的大量的同步器。
AQS核心思想是,如果被请求的共享资源空闲,则将当前请求资源的线程设置为有效的工作线程,并且将共享资源设置为锁定状态。如果被请求的共享资源被占用,那么就需要一套线程阻塞等待以及被唤醒时锁分配的机制,这个机制AQS是用CLH(虚拟的双向队列)队列锁实现的,即将暂时获取不到锁的线程加入到队列中。
整体概括
图片来源于:https://tech.meituan.com/2019/12/05/aqs-theory-and-apply.html
- 上图中有颜色的为Method,无颜色的为Attribution。
- 总的来说,AQS框架共分为五层,自上而下由浅入深,从AQS对外暴露的API到底层基础数据。
- 当有自定义同步器接入时,只需重写第一层所需要的部分方法即可,不需要关注底层具体的实现流程。当自定义同步器进行加锁或者解锁操作时,先经过第一层的API进入AQS内部方法,然后经过第二层进行锁的获取,接着对于获取锁失败的流程,进入第三层和第四层的等待队列处理,而这些处理方式均依赖于第五层的基础数据提供层。
CHL队列
介绍
Craig、Landin and Hagersten队列,是单向链表,AQS中的队列是CLH变体的虚拟双向队列(FIFO),AQS是通过将每条请求共享资源的线程封装成一个节点来实现锁的分配。
AQS使用一个Volatile的int类型的成员变量来表示同步状态,通过内置的FIFO队列来完成资源获取的排队工作,通过CAS完成对State值的修改。
NODE
Node为变体CLH队列中的节点
线程两种模式
模式 | 含义 |
---|---|
SHARED | 表示线程以共享的模式等待锁 |
EXCLUSIVE | 表示线程正在以独占的方式等待锁 |
waitStatus含义
枚举 | 含义 |
---|---|
0 | 当一个Node被初始化的时候的默认值 |
CANCELLED | 为1,表示线程获取锁的请求已经取消了 |
CONDITION | 为-2,表示节点在等待队列中,节点线程等待唤醒 |
PROPAGATE | 为-3,当前线程处在SHARED情况下,该字段才会使用 |
SIGNAL | 为-1,表示线程已经准备好了,就等资源释放了 |
同步状态state
private volatile int state;
方法名 | 描述 |
---|---|
protected final int getState() | 获取State的值 |
protected final void setState(int newState) | 设置State的值 |
protected final boolean compareAndSetState(int expect, int update) | 使用CAS方式更新State |
ConditionObject
AQS中的ConditionObject是一个条件队列,用于实现线程之间的等待和唤醒。
它是通过维护一个等待队列来实现的,每个ConditionObject对象维护了一个等待队列,当一个线程调用await方法时,会将该线程加入等待队列中,并阻塞该线程。当另一个线程调用signal或signalAll方法时,会从等待队列中选择一个或多个线程,将其从等待队列中移除,并唤醒这些线程,使其重新竞争获取同步状态。
整体概况
条件队列
可重写方法
主要是AQS概览里面的第一层
JDK中实现AQS简介
同步工具 | 与AQS关联 | 详细介绍 |
---|---|---|
ReentrantLock | 使用AQS保存锁重复持有的次数。当一个线程获取锁时,ReentrantLock记录当前获得锁的线程标识,用于检测是否重复获取,以及错误线程试图解锁操作时异常情况的处理。 | |
Semaphore | 使用AQS同步状态来保存信号量的当前计数。tryRelease会增加计数,acquireShared会减少计数。 |
自定义同步工具
待定
学习参考
1.https://juejin.cn/post/6844904179253657614#heading-16
2.https://tech.meituan.com/2019/12/05/aqs-theory-and-apply.html