当然可以,AQS(AbstractQueuedSynchronizer) 是 Java 并发包 java.util.concurrent
(简称 JUC)中非常核心的一个抽象类,是构建各种同步器(如 ReentrantLock
、Semaphore
、CountDownLatch
、ReentrantReadWriteLock
等)的基础框架。
一、AQS 的作用
AQS 的核心思想是:使用一个 int
类型的原子变量 state
来表示同步状态,并通过一个 FIFO 队列来管理等待获取锁的线程。
它提供了一套模板方法,允许子类通过实现特定的方法(如 tryAcquire
、tryRelease
)来定义同步语义,从而构建各种不同的同步组件。
二、AQS 的核心组成
1. 同步状态(state)
state
是一个volatile
修饰的int
类型变量,用于表示同步资源的状态。- 子类通过修改
state
的值来控制资源的获取与释放。 - AQS 提供了基于 CAS 的原子操作方法(如
compareAndSetState
)来修改state
,确保线程安全。
2. 同步队列(CLH 队列)
- AQS 内部维护了一个双向链表的同步队列(FIFO),用于管理等待获取锁的线程。
- 每个节点(
Node
)代表一个线程,包含线程引用、等待状态、前驱节点和后继节点等信息。 - 当线程尝试获取锁失败时,会被封装成一个
Node
插入到队列尾部,并进入等待状态。
3. Node 节点的状态(waitStatus)
每个 Node
有一个 waitStatus
字段,表示节点的等待状态,常见值如下:
状态值 | 含义 |
---|---|
0 | 默认状态,当前节点在队列中,等待获取锁 |
CANCELLED(1) | 当前线程被取消(可能因超时或中断) |
SIGNAL(-1) | 后续节点需要被唤醒 |
CONDITION(-2) | 当前节点在条件队列中 |
PROPAGATE(-3) | 表示释放共享锁时应传播唤醒操作(用于共享模式) |
三、AQS 的两种模式
AQS 支持两种同步模式:
1. 独占模式(Exclusive Mode)
- 一次只能有一个线程获取同步资源。
- 适用于
ReentrantLock
、ReentrantReadWriteLock.WriteLock
等。 - 相关方法:
acquire()
、release()
2. 共享模式(Shared Mode)
- 多个线程可以同时获取同步资源。
- 适用于
CountDownLatch
、Semaphore
、ReentrantReadWriteLock.ReadLock
等。 - 相关方法:
acquireShared()
、releaseShared()
四、AQS 的核心方法(模板方法)
AQS 提供了一系列公共方法,这些方法调用了子类实现的 钩子方法(如 tryAcquire
、tryRelease
)。主要方法如下:
方法名 | 说明 |
---|---|
acquire(int arg) | 独占方式获取同步状态,失败则进入队列等待 |
release(int arg) | 独占方式释放同步状态,唤醒后继节点 |
acquireShared(int arg) | 共享方式获取同步状态,失败则进入队列等待 |
releaseShared(int arg) | 共享方式释放同步状态,唤醒后继节点 |
这些方法内部调用了子类必须实现的钩子方法:
钩子方法 | 说明 |
---|---|
tryAcquire(int arg) | 独占方式尝试获取资源 |
tryRelease(int arg) | 独占方式尝试释放资源 |
tryAcquireShared(int arg) | 共享方式尝试获取资源 |
tryReleaseShared(int arg) | 共享方式尝试释放资源 |
五、AQS 的典型应用场景
同步组件 | 使用方式 | AQS 模式 | 说明 |
---|---|---|---|
ReentrantLock | 独占锁 | 独占模式 | 可重入、支持公平/非公平 |
Semaphore | 信号量 | 共享模式 | 控制同时访问的线程数量 |
CountDownLatch | 倒计时门闩 | 共享模式 | 所有线程等待一个倒计时完成 |
ReentrantReadWriteLock | 读写锁 | 独占 + 共享 | 读共享,写独占 |
FutureTask | 异步任务 | 独占 | 用于异步执行任务并获取结果 |
六、AQS 的优缺点
✅ 优点
- 高度抽象:提供统一的同步框架,简化了同步组件的开发。
- 高效性:基于 CAS 和队列管理,性能优秀。
- 灵活性:支持独占和共享两种模式,适用于多种同步场景。
- 可扩展性强:开发者可以基于 AQS 自定义同步组件。
❌ 缺点
- 理解成本高:内部逻辑复杂,涉及队列、CAS、线程状态管理等知识。
- 调试困难:死锁、阻塞等问题不容易排查。
七、总结
项目 | 说明 |
---|---|
核心机制 | 使用 state 表示同步状态,FIFO 队列管理等待线程 |
同步模式 | 独占模式、共享模式 |
实现方式 | 基于 CAS + volatile + 线程阻塞 |
核心设计 | 模板方法 + 钩子方法 |
应用场景 | ReentrantLock 、Semaphore 、CountDownLatch 等 |
优势 | 高效、灵活、可扩展 |
难点 | 实现复杂,调试困难 |
八、一句话总结 AQS:
AQS 是 Java 并发包中构建各种同步组件的核心框架,它通过一个原子状态变量和一个等待队列,实现了对线程的阻塞与唤醒机制,为开发者提供了统一的同步抽象模型。
如果你正在准备面试,建议结合 ReentrantLock
或 CountDownLatch
的源码,深入理解 AQS 的工作原理,这样可以更好地回答并发相关问题。
THE END