AQS (AbstractQueuedSynchronizer) 是 JDK 並發包核心基石,支援獨占/共享兩種同步模式。本文以 ReentrantLock 為切入點,深度剖析獨占鎖實現:狀態變數、CLH 隊列、CAS 自旋、公平/非公平策略、Condition 協作。
public class ReentrantLock implements Lock {
private final Sync sync;
abstract static class Sync extends AbstractQueuedSynchronizer { ... }
static final class NonfairSync extends Sync { ... }
static final class FairSync extends Sync { ... }
}
public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() && 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;
}
enq() 自旋入隊
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;
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed) cancelAcquire(node);
}
}
thread、waitStatus、prev/nextwaitStatus:SIGNAL(-1) 需喚醒後繼、CANCELLED(1) 取消、CONDITION(-2) 條件等待、PROPAGATE(-3) 共享傳播
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
waitStatus < 0 節點LockSupport.unpark(thread) 喚醒| 策略 | lock() 行為 | tryAcquire 邏輯 |
|---|---|---|
| 公平 | 直接進 AQS 流程 | !hasQueuedPredecessors() 檢查隊列 |
| 非公平 | 先 CAS 搶佔 state | 成功直接返回,失敗再進 AQS |
// 非公平鎖 lock()
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
acquire/release),子類實現規則 (tryAcquire/Release)state 可表鎖計數、信號量許可、倒數閂計數LockSupport.park/unpark 基於 UNSAFE/JNIReentrantReadWriteLock:同隊列混合獨占(寫)/共享(讀)節點FutureTask (JDK 1.6):獨占 API 實現結果獲取阻塞Semaphore:共享 API 實現許可證控制