CountDownLatch 的核心是 AQS 的 state 字段作为计数器:构造时设 state 为 count;countDown() 通过 CAS 减 1,仅减至 0 时唤醒所有等待线程;await() 仅读取 state 判断是否为 0 决定挂起;state 归零后不可重置。

CountDownLatch 的核心不是“倒计时”这个动作本身,而是 AQS 的 state 字段如何被当作计数器使用。所有行为——等待、释放、唤醒——都围绕 state 的读取、CAS 修改和状态判断展开。
构造时:count 直接设为 AQS 的 state
调用 new CountDownLatch(3) 时,内部会创建静态内部类 Sync(继承自 AbstractQueuedSynchronizer),并执行:
-
setState(count)—— 把传入的 3 直接写入 AQS 的state变量 - 此后整个生命周期中,
state就是那个“剩余等待数”
countDown():CAS 减 1,仅当减到 0 才触发唤醒
每次调用 countDown(),实际执行的是 sync.releaseShared(1),关键逻辑在 tryReleaseShared 中:
你接手一个需求时,是不是经常这样:"改一个小字段 → 结果把不相关的代码也改了"、"需求说得很模糊 → 做着做着发现跑偏了"、"数据库加个字段 → 上线才发现漏了数据兼容"、"做了个新功能 → 一个月后自己都忘了当时怎么设计的"、"写到一半被中断 → 再回来不知道从哪继续";这个 Skill 就是专门解决这些问题的。 它会自动探测你的项目环境(JDK、Spring Boot、ORM、数据库、前端框架),记在
- 循环读取当前
state值(记为c) - 若
c == 0,直接返回false(已归零,无需再减) - 否则尝试 CAS 将
state从c改为c - 1 - 只有当新值恰好等于 0 时,才返回
true,从而触发doReleaseShared()唤醒所有等待线程
await():靠 tryAcquireShared 判断 state 是否为 0
await() 调用的是 acquireSharedInterruptibly(1),其是否阻塞取决于 tryAcquireShared 的返回值:
立即学习“Java免费学习笔记(深入)”;
- 该方法只做一件事:
return (getState() == 0) ? 1 : -1; - 返回 1 → 获取成功,线程继续执行
- 返回 -1 → 获取失败,线程被封装为 Node 加入 AQS 同步队列,并调用
LockSupport.park()挂起 - 后续唤醒由
doReleaseShared()完成,它遍历同步队列,对每个处于 SIGNAL 状态的头节点调用unparkSuccessor()
关键提醒:state 是唯一真相
不需要记住“门闩”“倒计时”这些比喻,真正驱动一切的是:
-
state初始化即计数值 -
countDown()是原子减 1,但只在减到 0 时广播唤醒 -
await()不修改 state,只读取并决定是否挂起 - 没有“重置”或“重复使用”能力——state 归零后无法恢复,这是它与 CyclicBarrier 的根本区别

















