深度解析AbstractQueuedSynchronizer的实现原理与应用场景
使用volatile修饰,通过CAS原子操作控制状态转换
虚拟双向队列,管理等待线程的排队与唤醒
子类实现具体策略,父类处理通用逻辑
public class ReentrantLock implements Lock {
private final Sync sync; // 核心同步器
abstract static class Sync extends AQS {
abstract boolean initialTryLock();
final void lock() { ... }
protected final boolean tryRelease(int releases) { ... }
}
static final class NonfairSync extends Sync { ... } // 非公平锁
static final class FairSync extends Sync { ... } // 公平锁
}
获取锁失败
封装为Node节点
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node); // 自旋入队
return node;
}
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;
}
}
}
}
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node); // 成为新头节点
p.next = null; // 帮助GC
failed = false;
return interrupted;
}
// 判断是否应该阻塞
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed)
cancelAcquire(node); // 取消获取
}
}
节点创建时的默认状态
后继节点需要被唤醒
线程已取消等待
在条件队列中等待
共享模式下的唤醒传播
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; // 是否完全释放
}
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); // 唤醒线程
}
根据等待时间动态调整自旋次数,减少上下文切换开销
延迟清理CANCELLED状态节点,避免频繁的链表操作
从队尾向前遍历寻找有效节点,保证指针一致性
| 同步器 | 模式 | state含义 | 特点 |
|---|---|---|---|
| ReentrantLock | 独占 | 重入次数 | 可重入,支持公平/非公平 |
| Semaphore | 共享 | 许可证数量 | 控制并发访问数量 |
| CountDownLatch | 共享 | 计数器 | 一次性屏障,不可重置 |