登录
首页 >  文章 >  java教程

CyclicBarrier与CountDownLatch区别解析

时间:2026-02-04 16:12:45 357浏览 收藏

积累知识,胜过积蓄金银!毕竟在文章开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《CyclicBarrier与CountDownLatch区别详解》,就带大家讲解一下知识点,若是你对本文感兴趣,或者是想搞懂其中某个知识点,就请你继续往下看吧~

CountDownLatch适用于一次性等待所有操作完成,不可重置;CyclicBarrier适用于多线程循环协同,可重置并支持屏障中断与回调。二者语义不同,不可互换。

在Java里CyclicBarrier和CountDownLatch区别_Java同步工具说明

CountDownLatch 适合“等待一组操作全部完成”

它是一次性使用的计数器,初始化时指定一个 count,每次调用 countDown() 就减一,调用 await() 的线程会阻塞直到计数归零。常见于:主线程等所有子任务跑完再继续、服务启动时等待多个组件初始化完毕。

注意点:

  • CountDownLatch 不能重置,一旦计数到 0,后续所有 await() 都立即返回
  • 没有“唤醒所有等待线程后自动重置”的机制,所以不适合循环场景
  • 如果某线程调用 await() 后被中断,会抛 InterruptedException,需自行处理

CyclicBarrier 适合“多线程分阶段协同执行”

它更像一个“集合点”,多个线程各自执行一段逻辑后,在 await() 处等待彼此到达;当最后一个线程到达,所有线程同时被释放,并可选择执行一个 Runnable(如汇总统计)。典型场景:并行计算分片处理 + 汇总、多玩家准备就绪后开始游戏回合。

关键行为:

  • CyclicBarrier 可重复使用,计数归零后自动重置为初始值
  • 支持带超时的 await(long timeout, TimeUnit unit),超时后会抛 TimeoutException 并打破屏障
  • 任一线程在 await() 时被中断或超时,整个屏障进入 broke 状态,其他等待线程也会收到 BrokenBarrierException

别把它们当“可互换的等待工具”用

表面上都让线程等,但设计意图完全不同:

  • CountDownLatch 实现“多线程等一个信号”很简单,但反过来模拟 CyclicBarrier 的循环协作就得自己加锁 + 重置逻辑,容易出错
  • CyclicBarrier 做一次性等待也可以,但它的异常传播机制(BrokenBarrierException)和重入特性在单次场景里是冗余负担
  • 性能上差异不大,但语义误用会导致调试困难——比如看到 BrokenBarrierException 却用了 CountDownLatch,说明代码逻辑和工具选型不匹配

一个容易忽略的细节:线程到达顺序不影响 CyclicBarrier 行为

CyclicBarrier 不关心谁先到、谁后到,只关心“是否凑够 parties 个”。但要注意:Runnable 回调(如果设置了)是由最后一个到达的线程执行的,不是由某个固定线程执行。这意味着:

  • 回调里不要做耗时操作,否则会拖慢最后一个线程,进而影响下一轮等待的启动
  • 回调中若抛异常,会导致所有等待线程收到 BrokenBarrierException
  • 如果想在回调里安全更新共享状态,得确保该状态本身是线程安全的,或者回调已处于临界区保护下

本篇关于《CyclicBarrier与CountDownLatch区别解析》的介绍就到此结束啦,但是学无止境,想要了解学习更多关于文章的相关知识,请关注golang学习网公众号!

前往漫画官网入口并下载 ➜
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>