countdownlatch 的 await() 基于 aqs 共享模式实现,通过 state 计数器判断是否阻塞:state==0 时直接返回,否则入 aqs 队列并 park;不依赖 object#wait(),无 monitor 锁,支持中断,重复调用安全。

CountDownLatch 的 await() 并不是基于 Object#wait() 实现的,它底层完全依赖 AQS(AbstractQueuedSynchronizer)的共享模式,核心是检查并响应 state 值是否为 0。
state 是计数器,也是阻塞开关
AQS 的 state 字段被直接用作倒计数器。构造时传入的 count 就是初始 state 值。await() 本质是调用 sync.acquireSharedInterruptibly(1),而 sync 是 CountDownLatch 内部继承 AQS 的 Sync 类。它重写了 tryAcquireShared() 方法:
- 若
getState() == 0,返回 1 → 表示“获取共享许可成功”,线程不阻塞,直接继续执行; - 若
getState() > 0,返回 -1 → AQS 判定获取失败,将当前线程封装为 Node 加入同步队列(CLH 队列),并挂起(LockSupport.park());
等待线程不进 Object Monitor,而是进 AQS 同步队列
这和 synchronized + wait() 有本质区别:
- 没有 monitor 锁参与,不需要先获得锁再调用 await();
- 线程阻塞后处于 WAITING 状态,但等待的是 AQS 队列中的唤醒信号(由 countDown() 触发);
- 被唤醒后不是靠 notify/notifyAll,而是 AQS 在 state 变为 0 时遍历队列、逐个 unpark 所有等待节点。
中断支持靠 AQS 统一处理
await() 声明抛出 InterruptedException,是因为它调用的是 acquireSharedInterruptibly()。AQS 在 park 前会检查线程中断状态;若被中断,会立即抛出异常退出等待,不会进入队列或后续被唤醒。
多次 await 不会重复入队,但每次调用都重新校验 state
同一个线程反复调用 await() 是安全的:
- 第一次调用时 state > 0 → 入队挂起;
- 后续调用(即使已唤醒)仍会再次调用
tryAcquireShared(); - 只要此时 state == 0,就直接放行,不会二次入队。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











