CyclicBarrier的屏障动作是协调多阶段并发任务的关键控制点,由最后一个到达线程执行,用于轻量级同步操作,不可耗时或抛异常,配合可重用性实现多轮分阶段并行控制。

CyclicBarrier 的屏障动作(barrier action)不是附加功能,而是协调多阶段并发任务的关键控制点。它由最后一个到达的线程执行,天然具备“阶段切换”的时序权威性,配合其可重用特性,能构建出清晰、可控的多轮同步流程。
屏障动作的核心职责
屏障动作是一个 Runnable,在所有线程都调用 await() 后、唤醒其他线程前立即执行。它不运行在独立线程中,而是由最后一个抵达的工作者线程“顺带”完成。
- 适合做轻量级、无阻塞的协调操作:比如汇总各线程的局部计算结果、更新共享状态标志、触发下一阶段的初始化逻辑
- 不适合耗时或可能失败的操作:若 barrier action 抛异常(如 NullPointerException 或自定义检查失败),整个屏障会被标记为 broken,后续所有 await() 调用都会立即抛出
BrokenBarrierException - 它不参与计数,也不影响等待逻辑——只在“放行前一刻”执行一次,且仅本轮有效
多阶段任务中的同步策略
真正发挥 CyclicBarrier 价值的场景,是需要严格分阶段推进的并行计算。例如图像分块处理、迭代算法(Jacobi)、分布式模拟等。
- 每轮循环对应一个逻辑阶段:线程各自处理本地数据 → 全部到达屏障 → barrier action 合并/校验/广播 → 所有线程带着新上下文进入下一轮
- 利用
getNumberWaiting()可监控当前轮次是否卡住,辅助诊断死锁或线程丢失问题 - 结合超时版
await(long, TimeUnit)防止某线程长期失联导致整组挂起;超时后该线程抛TimeoutException,屏障自动 broken,其余等待者也会收到BrokenBarrierException
与 CountDownLatch 的关键分工差异
别把 CyclicBarrier 当成“可重用的 CountDownLatch”。它们解决的是不同维度的问题:
- CountDownLatch 是“一锤定音”型:用于一个操作等待多个前置任务完成(如主线程等所有子任务结束),或多个线程等待某个启动信号(如同时开始计时)。不可重用,计数归零即终止
- CyclicBarrier 是“来回协同”型:用于固定数量的线程彼此等待、反复同步。强调“同一批线程多次交汇”,强调阶段间的状态流转和协作节奏
- 典型混用模式:用 CountDownLatch 控制任务启动,用 CyclicBarrier 管理中间多轮迭代,再用另一个 CountDownLatch 收集最终结果
实战建议:避免常见陷阱
写对容易,写稳需要留意细节:
- 构造时指定的
parties必须与实际调用 await() 的线程数严格一致;少一个,屏障永远不触发;多一个,会因等待超时或中断而 broken - 不要在 barrier action 中调用同一个 CyclicBarrier 的 await(),会造成自己等待自己,直接死锁
- 若需在 barrier action 中执行异步操作(如发通知、写日志),应包裹 try-catch 并确保不向外抛异常,否则整轮同步失效
- reset() 方法会强行终止当前等待并新建 generation,适用于异常恢复场景,但会令所有正在 await() 的线程收到
BrokenBarrierException,需谨慎调用

















