在 Java 並發編程中,CountDownLatch 是一個極為實用的同步工具類,它允許一個或多個線程等待,直到其他線程完成的操作數量達到指定值。簡單來說,它就像一個倒數計時器:主線程呼叫 await() 進入等待狀態,每當一個子線程完成任務呼叫 countDown(),計數器就減 1;當計數器歸零時,所有等待的線程被釋放繼續執行。
例如應用啟動時需並行初始化多個服務(資料庫連接池、緩存預熱、配置載入等),主線程必須等待所有初始化任務完成才能對外提供服務。使用 CountDownLatch 可輕鬆實現「一鍵啟動、同步等待」的協調模式。
將大任務拆分為多個獨立子任務交由線程池並行執行,主線程在 await() 處阻塞;各工作線程完成分片後呼叫 countDown()。所有分片完成後,主線程繼續進行聚合或後續邏輯。
CountDownLatch 內部維護一個 Sync 類繼承自 AbstractQueuedSynchronizer (AQS),利用 AQS 的共享鎖機制:
setState(count),getState() 即獲取剩餘計數。tryAcquireShared 中,若 state == 0 返回 1(成功),否則返回 -1 進入等待隊列。tryReleaseShared 通過 CAS 將 state 減 1,若減至 0 返回 true 喚醒後繼節點。/** 核心同步器實現節選 */
private static final class Sync extends AbstractQueuedSynchronizer {
Sync(int count) { setState(count); }
int getCount() { return getState(); }
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1; // 計數歸零才能通行
}
protected boolean tryReleaseShared(int releases) {
for (;;) {
int c = getState();
if (c == 0) return false;
int nextc = c - 1;
if (compareAndSetState(c, nextc)) return nextc == 0;
}
}
}
public void await() throws InterruptedException { sync.acquireSharedInterruptibly(1); }
public void countDown() { sync.releaseShared(1); }
CyclicBarrier。finally 塊中呼叫 countDown(),否則主線程會永久阻塞。await(timeout, unit),配合日誌告警,避免單點故障導致整個流程卡死。CountDownLatch 以極簡的 API 解決了「一等多」的線程協作問題,底層借助 AQS 共享鎖實現高效阻塞與喚醒。掌握其原理與適用邊界,能讓你在高併發系統設計中遊刃有餘。