cyclicbarrier 可重复使用,因其通过 reentrantlock 保障计数与状态切换原子性、condition 实现“等齐再放行”的精准唤醒、generation 机制隔离轮次状态,三者协同支持多轮同步。

CyclicBarrier 的底层不是靠 AQS 直接实现,而是封装了 ReentrantLock 和 Condition 来完成线程协作——它用锁保护计数操作,用条件队列管理等待与唤醒,整个过程干净、可控、可重入。
为什么选 ReentrantLock 而不是 synchronized
ReentrantLock 提供了更精细的并发控制能力,CyclicBarrier 需要保证 count 递减的原子性 和 状态切换的安全性。比如多个线程同时调用 await(),必须确保只有一个线程能成功修改 count,其余线程要么阻塞、要么触发 barrierAction。synchronized 缺乏超时、中断响应、多条件队列等能力,而 ReentrantLock 支持:
- 显式加锁/解锁,配合 try-finally 避免死锁风险
- 可响应中断(lockInterruptibly)——CyclicBarrier.await() 可被 interrupt 中断
- 支持公平/非公平策略(虽 CyclicBarrier 默认用非公平,但底层具备扩展性)
Condition 是怎么配合完成“等齐再放行”的
CyclicBarrier 内部只定义了一个 Condition 实例(叫 trip),所有等待线程都注册在这个条件队列上:
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 线程调用 await() 后,先加锁 → 减 count → 判断是否为最后一个(count == 0)
- 如果不是最后一个,就执行 trip.await() 进入等待状态,释放锁并挂起
- 如果是最后一个,执行 barrierAction(如有)→ 调用 trip.signalAll() 唤醒全部等待线程
- 被唤醒的线程重新竞争锁,检查当前 generation 是否有效(防中断污染),然后返回
Generation 机制让“重用”真正安全
每次所有线程通过屏障后,CyclicBarrier 不是简单把 count 重置为 parties,而是:
- 新建一个 Generation 对象,标记新轮次
- 将 broken 状态归零,隔离上一轮的中断或异常影响
- count 重置为 parties,trip 条件队列自动清空(因 signalAll 已唤醒全部)
这样即使某轮被中断(broken = true),下一轮仍能正常启动,不会误判失败状态。
和 CountDownLatch 的关键区别就在这里
CountDownLatch 是单次倒计时器,基于 AQS 的 state 字段做递减,归零即不可逆;CyclicBarrier 是“有状态的循环门”,它的重用性来自三者协同:
- ReentrantLock —— 保障 count 修改和 generation 切换的原子性
- Condition —— 实现精准的“集体阻塞 + 集体唤醒”语义
- Generation —— 提供轮次隔离,使 reset 行为天然安全
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










