1. AQS 深入解析
1.1 什么是 AQS
AQS(AbstractQueuedSynchronizer,抽象队列同步器) 是 java.util.concurrent
包的核心基石。
它提供了一套通用的机制来管理同步状态(state) 、阻塞/唤醒线程 、管理等待队列。
JUC 下的各种锁(ReentrantLock
、ReentrantReadWriteLock
)以及并发工具类(Semaphore
、CountDownLatch
、CyclicBarrier
等)都是基于 AQS 实现的。
1.1.1 AQS 的核心思想

-
CLH 同步队列
- 全称:Craig, Landin, and Hagersten Queue
- 用来存储被阻塞的线程 ,是一个 FIFO 双向队列。
- FIFO 公平锁:等待时间最长的线程优先获得锁。
- 双向队列:支持从两端插入/删除节点(非公平锁可能插队)。
-
state 属性
- 用
volatile int state
表示资源状态。 - 对于
ReentrantLock
:state=0
→ 没有线程持有锁state>0
→ 锁被持有(可重入时 state++)
- 对于
CountDownLatch
:state=0
→ 计数器归零,线程可继续执行state>0
→ 继续阻塞
- 用
1.2 ReentrantLock 底层原理
sequenceDiagram
participant Thread1 as 线程1
participant ReentrantLock
participant AQS
participant CLHQueue as CLH队列
participant Thread2 as 线程2
Thread1->>ReentrantLock: lock()
ReentrantLock->>AQS: tryAcquire()
AQS-->>Thread1: 成功获取锁 (state=1)
Thread2->>ReentrantLock: lock()
ReentrantLock->>AQS: tryAcquire()
AQS-->>Thread2: 获取失败
AQS->>CLHQueue: 入队等待
CLHQueue-->>Thread2: 阻塞 (park)
Thread1->>ReentrantLock: unlock()
ReentrantLock->>AQS: tryRelease()
AQS->>CLHQueue: signalNext()
CLHQueue-->>Thread2: 唤醒 (unpark)
Thread2->>AQS: tryAcquire()
AQS-->>Thread2: 成功获取锁 (state=1)
1.2.1 公平锁 vs 非公平锁
- 公平锁:严格按照线程请求的顺序获取锁。
- 非公平锁:允许在合适的时机插队(比如锁刚释放时,直接抢占)。
1.2.2 以 ReentrantLock 为例

ReentrantLock
内部有 3 个与 AQS 相关的类:
- Sync(抽象类,继承 AQS)
- NonfairSync(非公平锁实现)
- FairSync(公平锁实现)
上锁流程(非公平锁)
1. lock() 方法
java
final void lock() {
if (!initialTryLock()) // 初次尝试获取锁
acquire(1); // 获取失败则进入 AQS 获取流程
}
2. NonfairSync.initialTryLock()
java
final boolean initialTryLock() {
Thread current = Thread.currentThread();
if (compareAndSetState(0, 1)) { // CAS 将 state 从 0 改为 1
setExclusiveOwnerThread(current);
return true;
} else if (getExclusiveOwnerThread() == current) { // 可重入
setState(getState() + 1);
return true;
}
return false;
}
3. AQS.acquire()
java
public final void acquire(int arg) {
if (!tryAcquire(arg)) // 再次尝试获取锁
acquire(null, arg, false, false, false, 0L); // 获取失败则进入队列等待
}
4. acquire(null, arg, false, false, false, 0L) 源码
java
final void acquire(Node node, int arg,
boolean shared, boolean interruptible,
boolean timed, long time) {
Thread current = Thread.currentThread();
if (node == null)
node = addWaiter(shared ? Node.SHARED : Node.EXCLUSIVE);
boolean failed = true;
try {
for (;;) { // 自旋
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) { // 轮到自己了,尝试获取锁
setHead(node); // 成为新的头节点
p.next = null; // 帮助 GC
failed = false;
return;
}
// 阻塞当前线程,等待被唤醒
if (shouldParkAfterFailedAcquire(p, node))
parkAndCheckInterrupt();
}
} finally {
if (failed)
cancelAcquire(node); // 获取失败则取消排队
}
}
简化理解:
- 加到等待队列(如果不是头节点)
- 自旋等待 ,直到前驱节点是
head
- 尝试获取锁 (
tryAcquire
) - 获取失败 → 阻塞(
park
)等待唤醒 - 获取成功 → 设为新的
head
节点,退出循环
tryAcquire(非公平锁)
java
protected final boolean tryAcquire(int acquires) {
if (getState() == 0 && compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(Thread.currentThread());
return true;
}
return false;
}
解锁流程
1. AQS.release()
java
public final boolean release(int arg) {
if (tryRelease(arg)) {
signalNext(head); // 唤醒下一个等待线程
return true;
}
return false;
}
2. tryRelease()
java
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (getExclusiveOwnerThread() != Thread.currentThread())
throw new IllegalMonitorStateException();
boolean free = (c == 0);
if (free)
setExclusiveOwnerThread(null);
setState(c);
return free;
}
3. signalNext()
java
private static void signalNext(Node h) {
Node s;
if (h != null && (s = h.next) != null && s.status != 0) {
s.getAndUnsetStatus(WAITING);
LockSupport.unpark(s.waiter);
}
}
1.3 总结:AQS 的工作原理
- state 表示同步状态 (
volatile int
,CAS 修改) - CLH 队列管理阻塞线程(FIFO)
- 获取锁流程 :
- 尝试直接获取锁(
tryAcquire
) - 失败 → 加入等待队列 → 自旋等待 → 阻塞
- 尝试直接获取锁(
- 释放锁流程 :
- 修改 state
- 唤醒队列中下一个等待的线程
💡 一句话概括 AQS
AQS 就是一个基于 CLH 队列的线程等待/唤醒框架,利用 CAS 操作管理
state
,让线程安全地获取和释放资源。