源码:java.util.concurrent.locks.AbstractQueuedSynchronizer 源码解析
1. TODO
2. 脑图
Xmind
Edraw
Hexo 地址
👉 http://blog.wangjia.ink/2025/09/01/源码:java.util.concurrent.locks.AbstractQueuedSynchronizer源码解析/
3. 基础部分
3.1. AbstractQueuedSynchronizer 概述
AbstractQueuedSynchronizer 是一个抽象类,继承了 java.util.concurrent.locks.AbstractOwnableSynchronizer,实现了 java.io.Serializable
[!NOTE] 注意事项
- 详见源码:
AbstractOwnableSynchronizer- 详见源码:
Serializable
obsidian内部链接:Hexo链接:- 需要注意的是:
Java8的AQS是只有Node的,没有ExclusiveNode、SharedNode、ConditionNode的
3.2. AbstractQueuedSynchronizer 应用场景
3.2.1. 同步器
同步器是一种协调多个线程执行的工具。它通过内部维护的状态(State),用于控制多个线程对一个或多个共享资源的访问,从而实现线程间的同步与协作
简单来说,多个线程需要先竞争同步器资源(即 State),只有竞争成功的线程才能访问共享资源。而 AQS 提供了一系列机制,使得多个线程能够 “高效且安全” 地竞争、释放 State
在基于 AQS 的同步器实现中,通常需要维护两种队列:
- 一条同步队列
- 同步队列用于管理那些尝试获取同步器资源,但暂时失败并暂时进入阻塞(
WAITING、TIMED_WAITING)的线程 AQS已经封装好了相关的节点类型(即Node、ExclusiveNode、SharedNode),并且提供了首尾哨兵节点。因此,我们的AQS实现类只需要在此基础上维护同步队列即可
- 同步队列用于管理那些尝试获取同步器资源,但暂时失败并暂时进入阻塞(
- 多条条件队列
- 条件队列用于管理那些已经获取同步器资源,但因业务条件不满足,而调用了
Condition.await,释放同步器资源并暂时进入阻塞(WAITING、TIMED_WAITING)的线程 AQS已经封装好了ConditionObject和相关的节点类型(即ConditionNode),一个ConditionObject实例就是一条条件队列。因此,我们的AQS实现类只需要根据自己的需要,创建并维护ConditionObject实例即可
- 条件队列用于管理那些已经获取同步器资源,但因业务条件不满足,而调用了
在不同的同步器实现中,State 和共享资源有不同的含义,例如在 ReentrantLock 中:
State表示锁的重入次数0- 表示锁空闲,线程可以尝试获取
1- 表示锁已被某个线程持有
n(n > 1)- 表示同一线程对该锁进行了
n次重入
- 表示同一线程对该锁进行了
- 共享资源表示加锁期间的操作
在使用 AQS 时,绝大多数情况下(约 99%)都是用来实现各种同步器(例如 ReentrantLock、Semaphore、CountDownLatch)。在这种情况下,我们可能需要使用到的以下内容:
AOS- 如果基于
AQS实现的是独占模式的同步器(例如ReentrantLock),就需要使用AOS记录当前独占该资源的线程 - 但是如果基于
AQS实现的是共享模式的同步器(例如Semaphore),那么AOS根本就用不到
- 如果基于
AQSState- 同步队列
- 条件队列
在使用 AQS 实现同步器时,通常的做法是:在同步器内部定义一个静态内部类(一般命名为 Sync),并让 Sync 继承 AbstractQueuedSynchronizer,而不是让同步器直接继承 AQS
当外部调用同步器的方法时,执行的流程大致为:外部调用同步器的方法 → 同步器调用 Sync 的方法 → Sync 调用 AQS 的方法
[!NOTE] 注意事项
- 猴哥的烦恼箱
(。•́︿•̀。):
- 在使用
AQS实现同步器时,为什么不直接让同步器直接继承AQS?
- 其实这里实际使用了
GOF设计模式之策略模式,以ReentrangLock为例RenntrantLock需要支持 “公平锁” 和 “非公平锁” 两种模式,而两者在竞争State的逻辑上完全不同- 但是
AQS只提供了竞争State的方法,因此具体的竞争逻辑必须由AQS的实现类来定义。- 如果同步器直接继承
AQS,就需要在每次操作中使用if...else if...else或switch...case...default判断公平锁或非公平锁,然后执行不同的竞争逻辑- 为了避免大量的
if...else if...else或switch...case...default判断,ReentrantLock就采用了策略模式ReentrantLock内部定义了两个静态内部类(即FairSync、NonFairSync),这两个类分别实现各自的竞争逻辑
3.2.2. 状态机
状态机通过内部维护的状态(State),用于表示其实例在生命周期中可能经历的各个阶段
在使用 AQS 时,有少数情况(约 1%)会用来实现状态机(例如 ThreadPoolExecutor.Worker)。在这种情况下,我们可能需要使用到以下内容:
AQSState
在不同的状态机实现中,State 有不同的含义,例如在 ThreadPoolExecutor.Worker 中:
-1Worker正在被实例化
0Worker并没有 “执行” 任务(正在从任务队列中获取任务)
1Worker正在 “执行” 任务
在使用 AQS 实现状态机时,通常的做法是:直接让状态机继承 AQS
[!NOTE] 注意事项
- 猴哥的烦恼箱
(。•́︿•̀。)
- 为什么实现状态机还要使用
AQS?我们直接在状态机内部维护一个State不就行了嘛?
- 因为
AQS提供了一系列机制,使得多个线程能够 “高效且安全” 地竞争、释放State- 而我们自己实现不一定能做到这么稳妥,而且只是在走 “
AQS” 的老路,不如直接复用最省心
4. 内部类
4.1. Node
详见源码:AbstractQueuedSynchronizer.Node
obsidian内部链接:Hexo链接:
4.2. ExclusiveNode
AbstractQueuedSynchronizer.ExclusiveNode 只是简单地继承了 AbstractQueuedSynchronizer.Node,为 AbstractQueuedSynchronizer.Node 增加了一层 “独占模式节点” 的标签,用来明确区分节点所处的语义
1 | |
[!NOTE] 注意事项
- 如果基于
AQS实现的是独占模式同步器(例如ReentrantLock),那么同步队列中的Node就应该是ExclusiveNode
4.3. SharedNode
AbstractQueuedSynchronizer.SharedNode 也只是简单地继承了 AbstractQueuedSynchronizer.Node,为 AbstractQueuedSynchronizer.Node 增加了一层 “共享模式节点” 的标签,用来明确区分节点所处的语义
1 | |
[!NOTE] 注意事项
- 如果基于
AQS实现的是共享模式同步器(例如Semaphore),那么同步队列中的Node就应该是SharedNode
4.4. ConditionObject
详见源码:AbstractQueuedSynchronizer.ConditionObject
obsidian内部链接:Hexo链接:
4.5. ConditionNode
详见源码:AbstractQueuedSynchronizer.ConditionNode
obsidian内部链接:Hexo链接:
5. 核心属性
1 | |
