谈谈你对AQS的理解
AbstractQueuedSynchronizer(简称 AQS)是 Java 并发包 java.util.concurrent 的核心基础组件之一,尤其是构建自定义同步器(如锁、信号量、栅栏等)的基础框架。理解 AQS 是深入掌握 Java 并发编程的关键步骤之一。
一、AQS 是什么?
AQS 全称:AbstractQueuedSynchronizer
是 Java 并发包中定义的一个用于构建锁和同步器的基础框架类,其核心原理是:以一个 int 状态值(state)和一个 FIFO 双向等待队列为基础,来控制线程的并发访问。
AQS 主要通过**“状态位 + 队列”实现线程之间的同步与通信**。
二、核心结构与关键点
| 组成部分 | 描述 |
|---|---|
state | 表示同步状态(例如是否已加锁) |
exclusive owner thread | 独占模式下记录当前持有锁的线程 |
CLH 队列 | FIFO 等待队列,保存获取同步状态失败的线程 |
Node | 队列中的元素,每个等待线程对应一个 Node 节点 |
compareAndSetState | 使用 CAS 原子操作保证线程安全 |
AQS 支持两种同步模式:
| 模式 | 描述 | 示例 |
|---|---|---|
| 独占(Exclusive) | 同一时间只允许一个线程获取资源 | ReentrantLock |
| 共享(Shared) | 同一资源可被多个线程共享 | CountDownLatch、Semaphore |
三、工作机制原理(独占模式)
以 ReentrantLock(独占) 为例,简化流程如下:
- 线程尝试通过
tryAcquire()获取锁 - 如果获取失败(即 state != 0),则构造
Node节点加入 AQS 的等待队列 - 后续线程通过
acquire()不断尝试获取锁 - 当前线程释放锁时调用
release(),并通知(unpark)下一个等待线程尝试获取锁
📌 AQS 不直接实现同步器逻辑,而是通过 模板方法模式,子类(如 ReentrantLock)需实现:
protected boolean tryAcquire(int arg);
protected boolean tryRelease(int arg);
四、核心方法解析(核心骨架)
1、独占模式核心方法
public final void acquire(int arg)
public final boolean release(int arg)
acquire():尝试获取锁(失败则入队)release():释放锁并唤醒下一个节点
2、共享模式核心方法
public final void acquireShared(int arg)
public final boolean releaseShared(int arg)
- 用于支持多个线程共享资源(如信号量)
五、典型实现示例(基于 AQS)
| 同步工具 | 使用模式 | 说明 |
|---|---|---|
ReentrantLock | 独占 | 可重入锁 |
Semaphore | 共享 | 控制并发线程数 |
CountDownLatch | 共享 | 等待其他线程完成 |
ReentrantReadWriteLock | 共享+独占 | 读共享,写独占 |
FutureTask | 独占 | 控制任务执行一次性完成 |
六、深入关键点
1. CLH 队列(链表队列)
AQS 使用了 CLH(Craig, Landin, and Hagersten)队列实现线程的排队等待,具有非阻塞、自旋的特性:
head → Node1 → Node2 → Node3 → ...
每个 Node 包含:
thread:线程本身waitStatus:等待状态(如SIGNAL,CANCELLED,CONDITION)prev/next:前后指针
2. 状态变量 state
- 所有同步器的核心状态都保存在
int state中; - 子类通过
getState()/setState()/compareAndSetState()操作; - 支持多重加锁(重入锁)或计数(如信号量 permits);
3. CAS 保证线程安全
protected final boolean compareAndSetState(int expect, int update)
AQS 依赖底层 Unsafe 类的 CAS 实现(Compare And Swap),避免加锁开销,实现非阻塞并发控制。
七、实战案例:自定义独占锁
class MyLock extends AbstractQueuedSynchronizer {
public boolean tryAcquire(int acquires) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
protected boolean tryRelease(int releases) {
setExclusiveOwnerThread(null);
setState(0);
return true;
}
public void lock() {
acquire(1);
}
public void unlock() {
release(1);
}
}
八、相关源码入口(JDK)
AbstractQueuedSynchronizer.java
GitHub 链接(OpenJDK):
🔗 https://github.com/openjdk/jdk/blob/master/src/java.base/share/classes/java/util/concurrent/locks/AbstractQueuedSynchronizer.java
九、学习资料推荐
- 《Java 并发编程实战》 – Brian Goetz
- 《深入理解 Java 虚拟机》 – 周志明
- JDK 官方文档:
🔗 https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/locks/AbstractQueuedSynchronizer.html - AQS 可视化图解:
https://tech.meituan.com/2019/12/05/aqs-theory-and-apply.html (推荐阅读)
十、总结:AQS 的优缺点
| 优点 | 缺点 |
|---|---|
| 统一并发控制框架,灵活性高 | 学习曲线陡峭 |
| 支持独占、共享模式切换 | 不易调试(底层依赖 CAS、自旋) |
| 高性能、非阻塞 | 使用不当容易死锁 |
更多详细内容请关注其他相关文章!