countdownlatch 基于 aqs 共享模式实现,本质是不可重置的一次性同步计数器:state 初始为 count,countdown() cas 减 1,await() 检查 state 是否为 0,为 0 则直接返回,否则挂起;state 归零后唤醒所有等待线程。

AQS(AbstractQueuedSynchronizer)是 CountDownLatch 的核心实现基础,它不通过“共享锁”语义来工作,而是利用 AQS 的共享模式同步状态(state)来协调线程等待与唤醒——CountDownLatch 本质上不是锁,而是一个一次性同步计数器。
CountDownLatch 的 state 表示剩余等待次数
CountDownLatch 构造时传入的 count 值被直接设为 AQS 的 volatile int state。每次调用 countDown(),就对 state 执行 CAS 减 1;当 state 变为 0,表示所有前置任务完成,所有阻塞在 await() 的线程将被唤醒。
- state > 0:说明还有未完成的任务,
await()线程会进入 AQS 队列并挂起(调用doAcquireSharedInterruptibly) - state == 0:表示门已打开,
await()直接返回,不再阻塞 - state 不可重置,CountDownLatch 是一次性使用的
await() 走的是 AQS 共享获取流程
await() 底层调用 AQS.acquireSharedInterruptibly(1),触发共享模式获取逻辑:
- 先调用
tryAcquireShared()—— CountDownLatch 重写了它,仅判断if (getState() == 0) return 1; else return -1; - 若返回 -1(即未达标),当前线程被包装为共享节点加入 AQS 同步队列,并调用
park()挂起 - 注意:这里没有“获取锁”的竞争过程,也没有持有资源的概念,只是“检查条件是否满足”
countDown() 触发共享唤醒机制
每次 countDown() 调用 AQS.releaseShared(1),最终执行到 doReleaseShared():
- CAS 尝试将 state 减 1;成功后检查是否已到 0
- 若 state 刚变为 0,则遍历 AQS 队列,唤醒所有处于 shared 模式且前驱节点正常的等待节点
- 唤醒不是逐个 unpark,而是通过
setHeadAndPropagate+doReleaseShared循环传播,确保所有 await 线程都被释放
为什么说它“不是锁”,但复用了 AQS 共享机制?
AQS 的共享模式本为类似 Semaphore 的资源分发设计,CountDownLatch 巧妙地将其“条件判断+批量唤醒”能力借用来表达“等待门开”语义:
- 没有 acquire/release 成对操作,没有 owner、没有重入,不维护持有者信息
- state 是纯计数值,不是可用资源数(Semaphore 中 state 表示剩余许可数,可重复 acquire/release)
- 唤醒逻辑依赖 state==0 这一全局信号,而非某个线程主动释放资源
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











