AbstractQueuedSynchronizer (AQS) 是 JUC 並發包核心基石,ReentrantLock、CountDownLatch、Semaphore 等均構建於其上。本文從 ReentrantLock 切入,深度剖析 AQS 獨占鎖實現。
volatile int 狀態變數,獨占鎖表「持鎖次數」,共享鎖表「可用資源數」Node 雙向鏈表,頭節點為佔用鎖線程,尾節點為最新入隊線程tryAcquire/tryRelease 留給子類實現具體語義NonfairSync.lock():先 compareAndSetState(0,1) 搶鎖,失敗進 acquire(1)AQS.acquire():tryAcquire() 失敗 → addWaiter(Node.EXCLUSIVE) 入隊 → acquireQueued() 自旋嘗試獲取acquireQueued():前驅為頭節點且 tryAcquire 成功 → setHead(node) 佔用鎖;否則檢查前驅 waitStatus == SIGNAL → LockSupport.park() 掛起FairSync.tryAcquire() 先檢查 hasQueuedPredecessors(),有排隊線程則不搶佔NonfairSync.lock() 直接 CAS 搶鎖,成功即佔用,可能導致飢餓但吞吐更高Sync.tryRelease(1):state--,歸零時 setExclusiveOwnerThread(null)AQS.release():釋放成功 → unparkSuccessor(head) 喚醒後繼節點unparkSuccessor():從尾部向前尋找 waitStatus < 0 的節點 → LockSupport.unpark(thread)CANCELLED(1) // 取消等待
SIGNAL(-1) // 後繼需喚醒
CONDITION(-2) // 條件隊列
PROPAGATE(-3) // 共享模式傳播
AQS 並未使用 synchronized 或特殊指令,純 Java 實現:volatile state + CAS + CLH 隊列 + LockSupport。子類只需實現 tryAcquire/tryRelease 定義語義,AQS 負責排隊、阻塞、喚醒、內存可見性。
CountDownLatch、Semaphore 使用 tryAcquireShared/tryReleaseShared,隊列節點 Node.SHARED,喚醒時傳播至所有共享節點。