CyclicBarrier核心逻辑是“等齐再发车”:最后一个线程到达时执行回调、唤醒全体并自动重置;其基于ReentrantLock+Condition+Generation实现,通过count递减至0判定到齐,generation隔离轮次,broken标志标识破损状态。

CyclicBarrier 的核心逻辑是“等齐再发车”:所有参与线程必须调用 await() 到达屏障点,最后一个到达者触发放行并可执行回调(barrierAction),之后屏障自动重置进入下一轮。它不是靠 AQS 直接实现,而是基于 ReentrantLock + Condition + Generation 三件套完成线程阻塞、唤醒与代次隔离。
屏障如何判断“到齐”并放行?
内部维护两个关键状态变量:
- count:初始值等于构造时传入的 parties,每有一个线程调用 await() 就减 1
- generation:一个内部静态类,含 broken 标志位,标识当前轮次是否失效
当 count 减至 0,说明本轮“到齐”,此时由最后一个线程执行三件事:
- 若设置了 barrierAction,立即在该线程上下文中执行(注意:不另起线程,勿在此做耗时操作)
- 调用 trip.signalAll() 唤醒所有等待线程
- 调用 nextGeneration() 创建新 Generation、重置 count = parties,开启下一轮
BrokenBarrierException 从哪来?
这个异常不是偶然抛出,而是屏障被主动“破坏”后的明确信号。触发条件包括:
- 任一等待线程被 interrupt()
- await() 超时(使用带超时参数的重载方法)
- barrierAction 执行过程中抛出未捕获异常
- 外部线程调用 reset() 且有线程正在 await 中
一旦发生上述任一情况,CyclicBarrier 会调用 breakBarrier() 方法:
- 设置 generation.broken = true
- 重置 count = parties
- 调用 trip.signalAll() 强制唤醒所有等待线程
被唤醒的线程不会继续等待,而是统一抛出 BrokenBarrierException,防止“误判到齐”导致逻辑错乱。
破损屏障怎么恢复?
破损状态不可自动修复,必须显式干预:
- 调用 reset() 是唯一官方恢复手段:它会清空 broken 标志、重置 count、新建 Generation
- 但 reset() 仅在无线程处于 await 等待态时才安全;若有线程正阻塞,reset() 会直接触发 breakBarrier,让所有等待线程收到异常
- 因此推荐做法:在 catch(BrokenBarrierException) 块中先检查 isBroken(),确认后立即 reset(),再决定是否重试或退出
为什么线程数不匹配就卡死?
CyclicBarrier 不校验“谁调用了 await”,只计数。常见陷阱:
- 构造时设为 4,但实际只启动了 3 个线程调用 await() → 第 4 个永远等不到,其余 3 个一直阻塞
- 某个线程因异常提前 return,未走到 await() → 同样造成计数缺口
- 多个任务批次混用同一个 CyclicBarrier 实例,但某批次线程数动态变化 → 计数失准
解决关键:确保每次调用 await() 的线程数严格等于 parties,且所有路径(包括异常分支)都覆盖到位。必要时配合日志或监控统计实际到达数。

















