AQS(AbstractQueuedSynchronizer)详解
AQS(java.util.concurrent.locks.AbstractQueuedSynchronizer)是Java并发包(JUC)的核心基础框架,用于构建锁(如ReentrantLock)和同步器(如Semaphore、CountDownLatch)。它通过 CLH队列(变种的双向链表) 管理线程的阻塞与唤醒,并提供了一套 模板方法,让开发者只需实现少量关键方法即可自定义同步器。
1. AQS 核心思想
AQS 的核心是一个 FIFO 等待队列 和一个 volatile 的 state(同步状态),通过 CAS 操作控制锁的获取与释放:
state(int 类型):表示锁的状态(如
ReentrantLock中,state=0表示未锁定,state>0表示被占用)。CLH 队列:存储等待锁的线程,采用 双向链表 结构(FIFO 公平锁)。
2. AQS 关键方法
AQS 采用 模板方法模式,子类只需实现以下方法:
| 方法名 | 说明 |
|---|---|
tryAcquire(int arg) | 尝试获取锁(需子类实现,返回 true 表示成功) |
tryRelease(int arg) | 尝试释放锁(需子类实现,返回 true 表示成功) |
tryAcquireShared(int arg) | 尝试获取共享锁(如 Semaphore、CountDownLatch) |
tryReleaseShared(int arg) | 尝试释放共享锁 |
isHeldExclusively() | 当前线程是否独占锁(用于 Condition 条件变量) |
示例:ReentrantLock 的 NonfairSync(非公平锁)实现:
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) { // CAS 尝试获取锁
setExclusiveOwnerThread(current); // 设置当前线程为锁持有者
return true;
}
}
else if (current == getExclusiveOwnerThread()) { // 可重入逻辑
int nextc = c + acquires;
if (nextc < 0) throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
3. AQS 的两种模式
AQS 支持 独占锁(Exclusive) 和 共享锁(Shared):
(1) 独占锁(Exclusive)
-
一次只有一个线程能获取锁(如
ReentrantLock)。 -
核心方法:
-
acquire(int arg)→ 调用tryAcquire(),失败则加入队列并阻塞。 -
release(int arg)→ 调用tryRelease(),成功后唤醒后续线程。
-
(2) 共享锁(Shared)
-
允许多个线程同时获取锁(如
Semaphore、CountDownLatch)。 -
核心方法:
-
acquireShared(int arg)→ 调用tryAcquireShared()。 -
releaseShared(int arg)→ 调用tryReleaseShared()。
-
4. AQS 的底层实现
(1) CLH 队列(Craig, Landin, and Hagersten 锁队列)
-
数据结构:双向链表(
Node节点),每个节点代表一个等待线程。 -
关键字段:
-
waitStatus:线程状态(CANCELLED、SIGNAL、CONDITION等)。 -
prev、next:前驱和后继节点。
-
-
入队:通过 CAS 操作将新节点加入队尾。
-
出队:头节点(head)释放锁后,唤醒后继节点。
(2) 自旋与阻塞
-
非公平锁:直接尝试 CAS 获取锁,失败后再入队(
ReentrantLock.NonfairSync)。 -
公平锁:直接加入队列,严格按 FIFO 获取锁(
ReentrantLock.FairSync)。
5. AQS 的应用
AQS 是 JUC 同步器的基础,几乎所有高级锁都基于它实现:
| 同步器 | 实现方式 |
|---|---|
ReentrantLock | 独占锁(支持公平/非公平) |
ReentrantReadWriteLock | 读锁(共享)、写锁(独占) |
Semaphore | 共享锁(控制并发数) |
CountDownLatch | 共享锁(等待所有任务完成) |
CyclicBarrier | 结合 Condition 实现 |
6. AQS 的优缺点
✅ 优点
-
灵活性:可自定义独占锁、共享锁、条件变量等。
-
高性能:通过 CAS 和 CLH 队列减少竞争。
-
广泛应用:JUC 大部分同步工具基于 AQS。
❌ 缺点
-
复杂性:需要理解模板方法模式和 CLH 队列。
-
不适用于所有场景:某些特殊同步需求可能需要更低级别的控制(如
VarHandle)。
详解&spm=1001.2101.3001.5002&articleId=149019999&d=1&t=3&u=480345bef32244a3bd7815a4796847dc)
1995

被折叠的 条评论
为什么被折叠?



