AbstractQueuedSynchronizer(AQS)深度解析
一、核心架构设计
1.1 基础数据结构
AQS通过同步状态(state)和CLH队列实现线程同步控制:
- state变量:
volatile int类型,表示同步状态(如锁重入次数、信号量许可数) - 双向链表队列:由Node节点组成,每个节点封装等待线程及状态信息
- 头尾指针:通过CAS操作维护队列的FIFO特性
// 核心成员变量
private transient volatile Node head;
private transient volatile Node tail;
private volatile int state;
1.2 Node节点结构
static final class Node {
static final Node SHARED = new Node();
static final Node EXCLUSIVE = null;
static final int CANCELLED = 1;
static final int SIGNAL = -1;
static final int CONDITION = -2;
static final int PROPAGATE = -3;
volatile int waitStatus;
volatile Node prev;
volatile Node next;
volatile Thread thread;
Node nextWaiter;
}
- waitStatus:线程等待状态(5种状态)
- nextWaiter:区分独占/共享模式(EXCLUSIVE/SHARED)
二、核心工作机制
2.1 独占模式(Exclusive)
2.1.1 获取锁流程
graph TD
A[调用acquire(arg)] --> B{tryAcquire(arg)}
B -->|成功| C[设置独占线程]
B -->|失败| D[addWaiter]
D --> E[acquireQueued]
E -->|自旋成功| F[获取锁]
E -->|阻塞等待| G[LockSupport.park]
2.1.2 关键方法
- tryAcquire:尝试获取锁(子类实现)
- addWaiter:将线程封装为Node加入队列尾部
- acquireQueued:自旋等待并阻塞
2.2 共享模式(Shared)
2.2.1 获取锁流程
graph TD
A[调用acquireShared(arg)] --> B{tryAcquireShared(arg)}
B -->|成功| C[传播唤醒]
B -->|失败| D[addWaiter]
D --> E[acquireSharedQueued]
2.2.2 关键方法
- tryAcquireShared:尝试获取共享资源(返回剩余许可数)
- doReleaseShared:释放时传播唤醒后续线程
三、关键实现原理
3.1 状态管理
- compareAndSetState:原子更新state值
protected final boolean compareAndSetState(int expect, int update) { return unsafe.compareAndSwapInt(this, stateOffset, expect, update); } - 状态传播:共享模式下通过CAS实现状态扩散
3.2 队列操作
- 入队:通过CAS将节点添加到队尾
private Node enq(final Node node) { for (;;) { Node t = tail; if (t == null) { // 初始化头节点 if (compareAndSetHead(new Node())) tail = head; } else { node.prev = t; if (compareAndSetTail(t, node)) { t.next = node; return t; } } } } - 出队:头节点线程唤醒后尝试获取锁
3.3 线程阻塞与唤醒
- LockSupport.park():挂起当前线程
- LockSupport.unpark():唤醒指定线程
- unparkSuccessor:唤醒后继节点
private void unparkSuccessor(Node node) { int ws = node.waitStatus; if (ws < 0) compareAndSetWaitStatus(node, ws, 0); Node s = node.next; if (s == null || s.waitStatus > 0) { s = null; for (Node t = tail; t != null && t != node; t = t.prev) if (t.waitStatus <= 0) s = t; } if (s != null) LockSupport.unpark(s.thread); }
四、模板方法模式
4.1 方法调用流程
graph TB
subgraph 获取锁
A[acquire] --> B{tryAcquire}
B -->|成功| C[设置独占线程]
B -->|失败| D[addWaiter]
D --> E[acquireQueued]
end
subgraph 释放锁
F[release] --> G{tryRelease}
G -->|成功| H[unparkSuccessor]
end
4.2 需重写方法
| 方法 | 作用 | 调用时机 |
|---|---|---|
| tryAcquire | 尝试获取独占锁 | acquire()时 |
| tryRelease | 尝试释放独占锁 | release()时 |
| tryAcquireShared | 尝试获取共享锁 | acquireShared()时 |
| tryReleaseShared | 尝试释放共享锁 | releaseShared()时 |
| isHeldExclusively | 判断是否独占锁 | 条件队列相关操作 |
五、经典实现案例
5.1 ReentrantLock
// 非公平锁实现
static final class NonfairSync extends Sync {
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
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;
}
}
5.2 Semaphore
protected int tryAcquireShared(int acquires) {
for (;;) {
int available = getState();
int remaining = available - acquires;
if (remaining < 0 || compareAndSetState(available, remaining))
return remaining;
}
}
六、性能优化策略
6.1 自旋等待
- 初始自旋次数:JDK1.8动态调整(根据历史成功率)
- 自适应自旋:减少线程阻塞开销
6.2 锁消除
通过逃逸分析消除无竞争锁:
// 局部变量锁会被消除
public void method() {
Object lock = new Object();
synchronized(lock) { // 编译后无同步代码
// 仅本线程访问
}
}
6.3 锁粗化
合并相邻同步块:
// 优化前
for(int i=0; i<100; i++) {
synchronized(lock) { doA(); }
}
// 优化后
synchronized(lock) {
for(int i=0; i<100; i++) doA();
}
七、设计精髓
- 模板方法模式:分离通用逻辑(队列管理)与定制逻辑(状态操作)
- 无锁化设计:通过CAS和自旋减少内核态切换
- 可扩展性:仅需实现1-4个抽象方法即可创建新同步器
- 高并发优化:非公平锁默认策略提升吞吐量