Lazy loaded image
🗒️CyclicBarrier jdk8 源码分析
Words 1750Read Time 5 min
2025-10-21
2025-11-13
type
Post
status
Published
date
Oct 21, 2025
slug
CyclicBarrier
summary
Java并发编程
tags
并发编程
JUC
category
源码阅读
icon
password
原文
CyclicBarrier(循环屏障)是 Java 并发包中的同步工具,用于让一组线程到达某个屏障点后再同时继续执行。与 CountDownLatch 不同,CyclicBarrier 可以重复使用(“循环” 特性),适合需要多轮协作的场景(如多阶段任务,每阶段需所有线程准备就绪后再开始)。
 
 

工作流程

notion image
工作线程调用 await 方法,首先需要竞争到锁。
拿到锁的线程,会先扣减 CyclicBarrier 的 count。count 经过扣减 >0 ,当前线程则会进入 Condition 中的队列中并且释放锁和进入阻塞状态(WAITTING),等待唤醒。
未能拿到锁的线程则会进入 Sync 队列,等待唤醒竞争锁。
假设 count 递减后为 0,说明所有线程都已到达屏障,唤醒所有在Condition 队列中的线程。
并且重置计数器和generation,表示本轮结束,开启下一次的屏障
 

核心方法

构造器

  • CyclicBarrier(int parties)
    • parties为线程数
  • CyclicBarrier(int parties, Runnable barrierAction)
    • barrierAction由最后一个线程到达时触发该 Runnable 运行

await

线程调用后会进入阻塞状态,直到所有线程到达屏障会被破坏
返回值为 线程的序号即第几个到达的
  • int await() 无限期等待
  • int await(long timeout, TimeUnit unit) 限时等待,超时后会被破坏屏障

源码解析

重要属性

count 为本轮的线程计数器。count在初始化和重置时等同于parties
parties 为参与的线程数。
Condition 条件队列,假设线程调用 await 成功,则线程进入该条件队列
Generation:
Generation是实现循环CyclicBarrier的核心类。
一轮结束会重新创建Generation对象

await

首先线程需要拿到锁,进行计数器的扣减。使用了ReentrantLock,扣减这一部分代码就无需使用自旋+CAS 操作。
(1) index=0,表示当前线程是最后一个到达屏障的线程。如果构造器使用的是带Runnable的,先执行该线程。
index=0 也表示本轮的线程任务都已结束,需要开启下一轮的循环。需要重置计数器等动作。
(2) 如果不是最后一个到达的线程就会进入自旋。
如果工作线程未出现异常,那么这个线程则会进入到 Condition中的队列,也就是在(3)处执行,当然当前线程需要释放锁,然后进入阻塞状态(WAITTING),到这里一个线程的 await 方法就结束了。
自旋的逻辑是保证线程在一定时间内,可以进入阻塞状态。

重置

当最后一个线程到达时,需要重置计数器,generation,以及唤醒所有在Condition 队列中的所有线程。这样才能进入下一轮的循环中。
generation 对象主要是用来维护本次循环的信息的。
  • 它内部维护了一个broken属性(布尔值),如果为 true 则表示本轮循环已被破坏。
  • 可以用来判断是否处于本轮中。
 
 
上一篇
JDK线程池源码分析
下一篇
CountDownLatch jdk8 源码分析

Comments
Loading...