JDK 8 CyclicBarrier 源码详解(详细注释版)
1. 类定义和基本属性
public class CyclicBarrier {
/**
* CyclicBarrier的核心同步控制对象
* 使用ReentrantLock和Condition实现同步
* 这种设计使得CyclicBarrier具有可重入性和条件等待能力
*
* 设计巧妙之处:
* - 使用ReentrantLock提供互斥访问
* - 使用Condition实现线程等待和唤醒
* - 支持可重入性,简化实现
* - 提供灵活的等待机制
*/
private final ReentrantLock lock = new ReentrantLock();
/**
* 等待条件对象
* 用于协调参与屏障的线程
* 当线程到达屏障点时等待,直到所有线程都到达
*
* Condition的作用:
* - 提供比Object.wait/notify更灵活的等待机制
* - 支持超时等待和可中断等待
* - 与ReentrantLock紧密结合
* - 提供更好的性能和可控性
*/
private final Condition trip = lock.newCondition();
/**
* 屏障的参与线程数量
* 这是屏障的基本配置,不可更改
* 必须有指定数量的线程调用await()才能突破屏障
*
* 设计考虑:
* - final修饰确保不可变性
* - 必须为正数
* - 决定了屏障的突破条件
*/
private final int parties;
/**
* 屏障突破时执行的回调命令
* 当所有线程都到达屏障点时执行
* 执行在最后一个到达线程所在的线程中
*
* 回调特点:
* - 在最后一个线程中执行
* - 可以为null(不执行任何操作)
* - 如果抛出异常,会影响所有等待线程
* - 提供屏障突破后的处理机会
*/
private final Runnable barrierCommand;
/**
* 当前的屏障生成号
* 用于区分不同的屏障周期
* 每次屏障突破后generation会更新
*
* Generation的作用:
* - 标识当前屏障周期
* - 支持屏障的可重用性
* - 避免过期的等待线程被错误唤醒
* - 提供屏障状态管理
*/
private Generation generation = new Generation();
/**
* Generation内部类
* 用于标识屏障的代数/周期
* 每次屏障突破都会创建新的Generation对象
*
* 设计目的:
* - 区分不同的屏障周期
* - 避免过期等待线程的问题
* - 支持屏障的可重用性
* - 提供简单的状态管理
*/
private static class Generation {
/**
* 屏障是否被破坏的标志
* 如果为true,表示屏障处于破坏状态
* 破坏状态下的await()调用会抛出BrokenBarrierException
*
* 破坏原因:
* - 线程被中断
* - 超时
* - 回调命令抛出异常
* - 手动调用reset()
*/
boolean broken = false;
}
/**
* 当前还在等待的线程数量
* 这是CyclicBarrier的核心状态变量
* 随着线程的到达而递减
*
* 计数过程:
* 1. 初始值等于parties
* 2. 每个线程调用await()时减1
* 3. 当减到0时,所有等待线程被唤醒
* 4. 屏障突破后重置为parties
*
* 线程安全性:
* - 通过ReentrantLock保护
* - 保证计数操作的原子性
* - 避免竞态条件
*/
private int count;
/**
* 默认构造方法(私有)
* 仅供内部使用,创建指定parties和barrierCommand的CyclicBarrier
*
* 初始化过程:
* 1. 验证parties参数的有效性
* 2. 设置parties和barrierCommand字段
* 3. 初始化count为parties
* 4. 创建Generation对象
*
* @param parties 参与线程数量
* @param barrierCommand 屏障突破时执行的回调命令
*/
private CyclicBarrier(int parties, Runnable barrierCommand) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierCommand;
}
/**
* 指定参与线程数量的构造方法
* @param parties 参与线程数量
*
* 构造过程:
* 1. 验证parties参数必须为正数
* 2. 调用私有构造方法
* 3. 不设置回调命令(为null)
*
* 参数说明:
* - parties必须大于0
* - parties决定了屏障的突破条件
* - 没有回调命令
*
* @throws IllegalArgumentException 如果parties小于等于0
*/
public CyclicBarrier(int parties) {
this(parties, null);
}
/**
* 指定参与线程数量和回调命令的构造方法
* @param parties 参与线程数量
* @param barrierAction 屏障突破时执行的回调命令
*
* 构造过程:
* 1. 验证parties参数必须为正数
* 2. 调用私有构造方法
* 3. 设置回调命令
*
* 参数说明:
* - parties必须大于0
* - barrierAction可以为null
* - 回调命令在最后一个线程中执行
*
* @throws IllegalArgumentException 如果parties小于等于0
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
this(parties, barrierAction);
}
2. 核心等待方法(详细注释)
/**
* 等待所有线程到达屏障点
* 当前线程会阻塞直到所有参与线程都调用此方法
*
* 等待过程:
* 1. 获取ReentrantLock锁
* 2. 检查屏障是否被破坏
* 3. 减少等待线程计数
* 4. 如果不是最后一个线程,进入等待状态
* 5. 如果是最后一个线程,执行回调命令并唤醒所有等待线程
* 6. 释放ReentrantLock锁
*
* 破坏处理:
* - 如果屏障被破坏,抛出BrokenBarrierException
* - 如果线程被中断,抛出InterruptedException
* - 如果超时,抛出TimeoutException
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(等待时间)
* 线程安全性:完全线程安全
*
* @return 当前线程在所有线程中的到达顺序(0表示最后一个到达)
* @throws InterruptedException 如果线程被中断
* @throws BrokenBarrierException 如果屏障被破坏
*/
public int await() throws InterruptedException, BrokenBarrierException {
try {
return dowait(false, 0L); // 调用内部等待方法,不使用超时
} catch (TimeoutException toe) {
throw new Error(toe); // 不可能发生的异常
}
}
/**
* 等待所有线程到达屏障点(带超时)
* 当前线程会阻塞直到所有参与线程都调用此方法或超时
*
* 超时处理:
* 1. 获取ReentrantLock锁
* 2. 检查屏障是否被破坏
* 3. 减少等待线程计数
* 4. 如果不是最后一个线程,进入等待状态
* 5. 在指定时间内等待,超时则破坏屏障
* 6. 如果是最后一个线程,执行回调命令并唤醒所有等待线程
* 7. 释放ReentrantLock锁
*
* 超时后果:
* - 超时的线程抛出TimeoutException
* - 屏障被破坏,其他等待线程抛出BrokenBarrierException
* - 所有后续的await()调用都会失败
*
* 时间复杂度:O(1) 平均情况,O(∞) 最坏情况(等待时间)
* 线程安全性:完全线程安全
*
* @param timeout 等待时间
* @param unit 时间单位
* @return 当前线程在所有线程中的到达顺序(0表示最后一个到达)
* @throws InterruptedException 如果线程被中断
* @throws BrokenBarrierException 如果屏障被破坏
* @throws TimeoutException 如果等待超时
*/
public int await(long timeout, TimeUnit unit)
throws InterruptedException,
BrokenBarrierException,
TimeoutException {
return dowait(true, unit.toNanos(timeout)); // 调用内部等待方法,使用超时
}
/**
* 实际的等待方法
* 实现CyclicBarrier的核心等待逻辑
*
* 核心算法:
* 1. 获取ReentrantLock锁保护临界区
* 2. 检查屏障状态和线程状态
* 3. 更新等待线程计数
* 4. 根据情况决定等待、唤醒或破坏屏障
* 5. 执行回调命令(如果是最后一个线程)
* 6. 唤醒所有等待线程
* 7. 释放锁并返回结果
*
* 算法特点:
* - 原子性:通过锁保证操作的原子性
* - 一致性:维护屏障状态的一致性
* - 完整性:处理各种异常情况
* - 可重用性:屏障突破后可重复使用
*
* @param timed 是否使用超时
* @param nanos 超时时间(纳秒)
* @return 当前线程在所有线程中的到达顺序
* @throws InterruptedException 如果线程被中断
* @throws BrokenBarrierException 如果屏障被破坏
* @throws TimeoutException 如果等待超时
*/
private int dowait(boolean timed, long nanos)
throws InterruptedException, BrokenBarrierException,
TimeoutException {
final ReentrantLock lock = this.lock;
lock.lock(); // 获取锁
try {
final Generation g = generation; // 获取当前代数
// 检查屏障是否被破坏
if (g.broken)
throw new BrokenBarrierException();
// 检查线程是否被中断
if (Thread.interrupted()) {
breakBarrier(); // 破坏屏障
throw new InterruptedException();
}
int index = --count; // 减少等待线程计数
if (index == 0) { // 如果是最后一个线程
boolean ranAction = false;
try {
final Runnable command = barrierCommand;
if (command != null)
command.run(); // 执行回调命令
ranAction = true;
nextGeneration(); // 进入下一代
return 0;
} finally {
if (!ranAction)
breakBarrier(); // 如果回调命令执行失败,破坏屏障
}
}
// 不是最后一个线程,进入等待状态
for (;;) {
try {
if (!timed)
trip.await(); // 无限期等待
else if (nanos > 0L)
nanos = trip.awaitNanos(nanos); // 超时等待
} catch (InterruptedException ie) {
if (g == generation && ! g.broken) {
breakBarrier(); // 破坏屏障
throw ie;
} else {
Thread.currentThread().interrupt(); // 恢复中断状态
}
}
if (g.broken)
throw new BrokenBarrierException();
if (g != generation)
return index;
if (timed && nanos <= 0L) {
breakBarrier(); // 超时,破坏屏障
throw new TimeoutException();
}
}
} finally {
lock.unlock(); // 释放锁
}
}
/**
* 破坏屏障
* 将当前屏障设置为破坏状态并唤醒所有等待线程
*
* 破坏过程:
* 1. 设置当前代数的broken标志为true
* 2. 唤醒所有在trip条件上等待的线程
* 3. 重置等待线程计数
*
* 使用场景:
* - 线程被中断时
* - 等待超时时
* - 回调命令执行失败时
* - 手动调用reset()时
*
* 线程安全性:通过ReentrantLock保护
*/
private void breakBarrier() {
generation.broken = true;
count = parties;
trip.signalAll();
}
/**
* 进入下一代
* 屏障突破后调用,准备下一轮使用
*
* 更新过程:
* 1. 唤醒所有等待线程
* 2. 重置等待线程计数为parties
* 3. 创建新的Generation对象
*
* 设计目的:
* - 支持屏障的可重用性
* - 区分不同的屏障周期
* - 避免过期等待线程的问题
* - 保持屏障状态的一致性
*
* 线程安全性:通过ReentrantLock保护
*/
private void nextGeneration() {
trip.signalAll(); // 唤醒所有等待线程
count = parties; // 重置等待线程计数
generation = new Generation(); // 创建新的代数
}
3. 查询和控制方法(详细注释)
/**
* 获取参与屏障的线程数量
* 返回创建屏障时指定的参与线程数量
*
* 查询过程:
* 1. 直接返回parties字段
* 2. parties字段是final的,线程安全
*
* 时间复杂度:O(1)
* 线程安全性:完全线程安全
*
* @return 参与屏障的线程数量
*/
public int getParties() {
return parties;
}
/**
* 查询屏障是否被破坏
* 检查当前屏障是否处于破坏状态
*
* 查询过程:
* 1. 获取ReentrantLock锁
* 2. 检查当前代数的broken标志
* 3. 释放ReentrantLock锁
* 4. 返回检查结果
*
* 破坏状态说明:
* - true:屏障被破坏,await()调用会失败
* - false:屏障正常,可以正常使用
*
* 时间复杂度:O(1)
* 线程安全性:完全线程安全
*
* @return 如果屏障被破坏返回true,否则返回false
*/
public boolean isBroken() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return generation.broken;
} finally {
lock.unlock();
}
}
/**
* 获取当前还在等待的线程数量
* 返回还需要多少线程到达屏障点
*
* 查询过程:
* 1. 获取ReentrantLock锁
* 2. 返回当前count字段值
* 3. 释放ReentrantLock锁
*
* 注意事项:
* - 这是一个瞬时值,可能很快过时
* - 在高并发环境下可能不是准确值
* - 主要用于调试和监控
*
* 时间复杂度:O(1)
* 线程安全性:完全线程安全
*
* @return 当前还在等待的线程数量
*/
public int getNumberWaiting() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
return parties - count;
} finally {
lock.unlock();
}
}
/**
* 重置屏障
* 将屏障恢复到初始状态
*
* 重置过程:
* 1. 获取ReentrantLock锁
* 2. 破坏当前屏障
* 3. 进入下一代
* 4. 释放ReentrantLock锁
*
* 使用场景:
* - 清理屏障状态
* - 重新开始新一轮同步
* - 处理异常情况
*
* 注意事项:
* - 正在等待的线程会收到BrokenBarrierException
* - 屏障恢复到初始状态
* - 可以重新使用
*
* 时间复杂度:O(1)
* 线程安全性:完全线程安全
*/
public void reset() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
breakBarrier(); // 破坏当前屏障
nextGeneration(); // 进入下一代
} finally {
lock.unlock();
}
}
4. CyclicBarrier 的特点分析
核心设计理念:
/**
* CyclicBarrier的核心设计思想:
*
* 1. 屏障同步机制:
* - 多个线程相互等待到达一个共同点
* - 当所有线程都到达后,同时继续执行
* - 提供分阶段同步的能力
*
* 2. 可重用性:
* - 屏障突破后可以重复使用
* - 通过Generation机制区分不同的周期
* - 支持多次同步操作
*
* 3. 回调机制:
* - 支持屏障突破时的回调操作
* - 回调在最后一个到达线程中执行
* - 提供屏障突破后的处理机会
*
* 4. 状态管理:
* - 使用Generation标识不同的屏障周期
* - 通过broken标志管理屏障状态
* - 支持屏障的破坏和重置
*
* 5. 线程安全:
* - 使用ReentrantLock保护临界区
* - 使用Condition实现线程等待和唤醒
* - 所有操作都是线程安全的
*
* 6. 异常处理:
* - 支持线程中断处理
* - 支持超时处理
* - 支持回调异常处理
* - 提供详细的异常信息
*
* 7. 灵活的等待机制:
* - 支持无限期等待
* - 支持可中断等待
* - 支持超时等待
* - 提供多种等待选项
*
* 8. 高效的唤醒机制:
* - 屏障突破时一次性唤醒所有等待线程
* - 避免逐个唤醒的开销
* - 提高唤醒效率
*
* 适用场景:
* - 分阶段并行计算
* - 多线程协同工作
* - 需要同步点的场景
* - 可重复使用的同步需求
* - 需要回调处理的场景
*/
性能特征分析:
/**
* CyclicBarrier的性能特征:
*
* 时间复杂度:
* - await(): O(1) 平均情况,O(∞) 最坏情况(等待时间)
* - isBroken(): O(1)
* - getNumberWaiting(): O(1)
* - reset(): O(1)
* - getParties(): O(1)
*
* 空间复杂度:
* - O(1) 基本存储空间
* - O(n) 等待队列空间(n为等待线程数)
* - 每个实例固定开销很小
*
* 并发特性:
* - 完全线程安全
* - 支持高并发读写
* - 无死锁风险
* - 支持可重入性
*
* 与CountDownLatch对比:
* - CyclicBarrier > CountDownLatch(可重用性)
* - CyclicBarrier > CountDownLatch(回调支持)
* - CountDownLatch > CyclicBarrier(简单性)
* - CountDownLatch > CyclicBarrier(性能)
*
* 与ReentrantLock对比:
* - CyclicBarrier > ReentrantLock(专门化)
* - ReentrantLock > CyclicBarrier(灵活性)
* - CyclicBarrier > ReentrantLock(易用性)
*
* 内存使用:
* - 每个实例固定开销很小
* - 等待线程会增加内存使用
* - 及时GC,避免内存泄漏
*
* 适用性:
* - 分阶段同步:性能优异
* - 简单等待:可能不如CountDownLatch
* - 复杂同步:性能优异
* - 需要重置:完美匹配
*
* 性能优化:
* - 合理设置参与线程数量
* - 避免不必要的等待
* - 使用超时机制避免无限等待
* - 正确处理中断异常
* - 监控等待线程数量
*/
5. 使用示例和最佳实践
/**
* 使用示例:
*
* // 基本使用:分阶段并行计算
* class MatrixMultiplier {
* private final int[][] matrixA;
* private final int[][] matrixB;
* private final int[][] result;
* private final int rows;
* private final int cols;
*
* public MatrixMultiplier(int[][] a, int[][] b) {
* this.matrixA = a;
* this.matrixB = b;
* this.rows = a.length;
* this.cols = b[0].length;
* this.result = new int[rows][cols];
* }
*
* public int[][] multiply() throws InterruptedException, BrokenBarrierException {
* int numThreads = Runtime.getRuntime().availableProcessors();
* CyclicBarrier barrier = new CyclicBarrier(numThreads, () -> {
* System.out.println("All threads completed phase");
* });
*
* Thread[] workers = new Thread[numThreads];
* int rowsPerThread = rows / numThreads;
*
* for (int i = 0; i < numThreads; i++) {
* final int startRow = i * rowsPerThread;
* final int endRow = (i == numThreads - 1) ? rows : (i + 1) * rowsPerThread;
* workers[i] = new Thread(new Worker(startRow, endRow, barrier));
* workers[i].start();
* }
*
* // 等待所有线程完成
* for (Thread worker : workers) {
* worker.join();
* }
*
* return result;
* }
*
* private class Worker implements Runnable {
* private final int startRow;
* private final int endRow;
* private final CyclicBarrier barrier;
*
* Worker(int startRow, int endRow, CyclicBarrier barrier) {
* this.startRow = startRow;
* this.endRow = endRow;
* this.barrier = barrier;
* }
*
* public void run() {
* try {
* // 第一阶段:计算矩阵乘法的一部分
* for (int i = startRow; i < endRow; i++) {
* for (int j = 0; j < cols; j++) {
* for (int k = 0; k < matrixB.length; k++) {
* result[i][j] += matrixA[i][k] * matrixB[k][j];
* }
* }
* }
*
* System.out.println("Thread " + Thread.currentThread().getName() +
* " completed phase 1");
* barrier.await(); // 第一阶段屏障
*
* // 第二阶段:验证计算结果
* for (int i = startRow; i < endRow; i++) {
* for (int j = 0; j < cols; j++) {
* if (result[i][j] < 0) {
* System.err.println("Negative result detected at [" +
* i + "," + j + "]");
* }
* }
* }
*
* System.out.println("Thread " + Thread.currentThread().getName() +
* " completed phase 2");
* barrier.await(); // 第二阶段屏障
*
* } catch (InterruptedException | BrokenBarrierException e) {
* Thread.currentThread().interrupt();
* System.err.println("Worker thread interrupted: " + e.getMessage());
* }
* }
* }
* }
*
* // 带超时的使用示例
* CyclicBarrier timeoutBarrier = new CyclicBarrier(3, () -> {
* System.out.println("All threads reached barrier");
* });
*
* for (int i = 0; i < 3; i++) {
* final int threadId = i;
* new Thread(() -> {
* try {
* System.out.println("Thread " + threadId + " started");
* Thread.sleep(1000); // 模拟工作
* System.out.println("Thread " + threadId + " waiting at barrier");
*
* // 带超时的等待
* if (timeoutBarrier.await(5, TimeUnit.SECONDS) == 0) {
* System.out.println("Thread " + threadId + " was the last to arrive");
* } else {
* System.out.println("Thread " + threadId + " arrived at barrier");
* }
* } catch (InterruptedException e) {
* System.out.println("Thread " + threadId + " interrupted");
* Thread.currentThread().interrupt();
* } catch (BrokenBarrierException e) {
* System.out.println("Thread " + threadId + " barrier broken: " + e.getMessage());
* } catch (TimeoutException e) {
* System.out.println("Thread " + threadId + " timed out at barrier");
* // 可以选择重置屏障
* timeoutBarrier.reset();
* }
* }).start();
* }
*
* // 多轮同步示例
* class MultiRoundSynchronization {
* private final CyclicBarrier round1Barrier;
* private final CyclicBarrier round2Barrier;
* private final int numPlayers = 4;
*
* public MultiRoundSynchronization() {
* round1Barrier = new CyclicBarrier(numPlayers, () -> {
* System.out.println("=== Round 1 Complete ===");
* });
* round2Barrier = new CyclicBarrier(numPlayers, () -> {
* System.out.println("=== Round 2 Complete ===");
* });
* }
*
* public void playGame() {
* Thread[] players = new Thread[numPlayers];
* for (int i = 0; i < numPlayers; i++) {
* final int playerId = i;
* players[i] = new Thread(() -> {
* try {
* playRound1(playerId);
* round1Barrier.await(); // 第一轮结束屏障
*
* playRound2(playerId);
* round2Barrier.await(); // 第二轮结束屏障
*
* System.out.println("Player " + playerId + " finished game");
* } catch (Exception e) {
* System.err.println("Player " + playerId + " error: " + e.getMessage());
* Thread.currentThread().interrupt();
* }
* });
* players[i].start();
* }
*
* // 等待所有玩家完成
* for (Thread player : players) {
* try {
* player.join();
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* }
* }
* }
*
* private void playRound1(int playerId) {
* System.out.println("Player " + playerId + " playing round 1");
* try {
* Thread.sleep(1000 + playerId * 100); // 模拟不同时间的游戏
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* }
* System.out.println("Player " + playerId + " finished round 1");
* }
*
* private void playRound2(int playerId) {
* System.out.println("Player " + playerId + " playing round 2");
* try {
* Thread.sleep(1500 + playerId * 50); // 模拟不同时间的游戏
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* }
* System.out.println("Player " + playerId + " finished round 2");
* }
* }
*
* // 异常处理示例
* class ExceptionHandlingExample {
* private final CyclicBarrier barrier = new CyclicBarrier(3, () -> {
* System.out.println("Barrier action executing...");
* // 模拟回调命令抛出异常
* if (Math.random() < 0.3) { // 30%概率抛出异常
* throw new RuntimeException("Barrier action failed");
* }
* System.out.println("Barrier action completed");
* });
*
* public void runWithErrorHandling() {
* for (int i = 0; i < 3; i++) {
* final int threadId = i;
* new Thread(() -> {
* try {
* System.out.println("Thread " + threadId + " working...");
* Thread.sleep(1000);
* System.out.println("Thread " + threadId + " waiting at barrier");
*
* int arrivalIndex = barrier.await();
* System.out.println("Thread " + threadId + " passed barrier, " +
* "arrival index: " + arrivalIndex);
* } catch (InterruptedException e) {
* System.out.println("Thread " + threadId + " interrupted");
* Thread.currentThread().interrupt();
* } catch (BrokenBarrierException e) {
* System.out.println("Thread " + threadId + " barrier broken: " +
* e.getMessage());
* // 可以选择重置屏障
* if (!barrier.isBroken()) {
* barrier.reset();
* }
* }
* }).start();
* }
* }
* }
*
* 最佳实践:
*
* 1. 正确处理异常:
* CyclicBarrier barrier = new CyclicBarrier(3);
*
* // 正确的做法:处理所有可能的异常
* new Thread(() -> {
* try {
* // 执行任务
* performTask();
*
* // 等待屏障
* int arrivalIndex = barrier.await();
* System.out.println("Arrival index: " + arrivalIndex);
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt(); // 恢复中断状态
* System.err.println("Thread interrupted: " + e.getMessage());
* } catch (BrokenBarrierException e) {
* System.err.println("Barrier broken: " + e.getMessage());
* // 可以选择重置屏障
* if (!barrier.isBroken()) {
* barrier.reset();
* }
* }
* }).start();
*
* // 错误的做法:忽略异常
* // new Thread(() -> {
* // barrier.await(); // 没有处理异常
* // }).start();
*
* 2. 合理使用回调命令:
* CyclicBarrier barrier = new CyclicBarrier(4, () -> {
* // 在回调命令中执行轻量级操作
* System.out.println("All threads reached barrier at: " +
* new Date(System.currentTimeMillis()));
*
* // 避免在回调命令中执行耗时操作
* // 避免在回调命令中抛出异常(会影响所有等待线程)
* });
*
* // 错误的做法:在回调命令中执行耗时操作
* // CyclicBarrier badBarrier = new CyclicBarrier(4, () -> {
* // Thread.sleep(5000); // 耗时操作会阻塞所有线程
* // });
*
* 3. 使用超时机制:
* CyclicBarrier barrier = new CyclicBarrier(3);
*
* // 使用超时避免无限等待
* new Thread(() -> {
* try {
* if (barrier.await(10, TimeUnit.SECONDS) == 0) {
* System.out.println("Last thread to arrive");
* } else {
* System.out.println("Arrived at barrier");
* }
* } catch (InterruptedException e) {
* Thread.currentThread().interrupt();
* } catch (BrokenBarrierException e) {
* System.err.println("Barrier broken: " + e.getMessage());
* } catch (TimeoutException e) {
* System.err.println("Timed out waiting for barrier");
* // 处理超时情况
* barrier.reset(); // 重置屏障
* }
* }).start();
*
* 4. 正确设置参与线程数量:
* // 根据实际需求设置parties
* int actualThreadCount = calculateActualThreadCount();
* CyclicBarrier barrier = new CyclicBarrier(actualThreadCount);
*
* // 错误的做法:硬编码parties值
* // CyclicBarrier wrongBarrier = new CyclicBarrier(10); // 可能与实际线程数不符
*
* 5. 避免死锁:
* CyclicBarrier barrier1 = new CyclicBarrier(2);
* CyclicBarrier barrier2 = new CyclicBarrier(2);
*
* // 错误的做法:可能导致死锁
* // Thread t1 = new Thread(() -> {
* // try {
* // barrier1.await();
* // barrier2.await(); // 可能与另一个线程形成死锁
* // } catch (Exception e) { /* 处理异常 */ }
* // });
* //
* // Thread t2 = new Thread(() -> {
* // try {
* // barrier2.await(); // 可能与另一个线程形成死锁
* // barrier1.await();
* // } catch (Exception e) { /* 处理异常 */ }
* // });
*
* // 正确的做法:保持一致的屏障获取顺序
* Thread t1 = new Thread(() -> {
* try {
* barrier1.await();
* barrier2.await();
* } catch (Exception e) { /* 处理异常 */ }
* });
*
* Thread t2 = new Thread(() -> {
* try {
* barrier1.await(); // 保持相同的获取顺序
* barrier2.await();
* } catch (Exception e) { /* 处理异常 */ }
* });
*
* 6. 监控屏障状态:
* CyclicBarrier barrier = new CyclicBarrier(5);
*
* // 定期检查屏障状态
* public void monitorBarrier() {
* System.out.println("Parties: " + barrier.getParties());
* System.out.println("Waiting: " + barrier.getNumberWaiting());
* System.out.println("Broken: " + barrier.isBroken());
* }
*
* // 在高负载时监控性能
* public void performanceMonitoring() {
* long startTime = System.nanoTime();
* try {
* barrier.await();
* } catch (Exception e) {
* Thread.currentThread().interrupt();
* }
* long endTime = System.nanoTime();
* System.out.println("Barrier wait time: " + (endTime - startTime) + " ns");
* }
*
* 7. 合理使用reset()方法:
* CyclicBarrier barrier = new CyclicBarrier(3);
*
* // 在异常情况下重置屏障
* public void handleException() {
* if (barrier.isBroken()) {
* System.out.println("Barrier is broken, resetting...");
* barrier.reset();
* System.out.println("Barrier reset completed");
* }
* }
*
* // 避免频繁重置
* // barrier.reset(); // 不必要的重置会影响性能
*
* 8. 正确处理线程中断:
* CyclicBarrier barrier = new CyclicBarrier(3);
*
* Thread worker = new Thread(() -> {
* try {
* // 执行任务
* performTask();
*
* // 等待屏障
* barrier.await();
* System.out.println("Task completed successfully");
* } catch (InterruptedException e) {
* System.out.println("Task interrupted");
* Thread.currentThread().interrupt(); // 恢复中断状态
* } catch (BrokenBarrierException e) {
* System.err.println("Barrier broken due to interruption");
* }
* });
*
* worker.start();
*
* // 在适当时候中断线程
* // worker.interrupt(); // 可以优雅地中止任务
*
* 9. 使用多个屏障实现复杂同步:
* class ComplexSynchronization {
* private final CyclicBarrier phase1Barrier;
* private final CyclicBarrier phase2Barrier;
* private final CyclicBarrier completionBarrier;
*
* public ComplexSynchronization(int threadCount) {
* phase1Barrier = new CyclicBarrier(threadCount, () -> {
* System.out.println("Phase 1 completed");
* });
* phase2Barrier = new CyclicBarrier(threadCount, () -> {
* System.out.println("Phase 2 completed");
* });
* completionBarrier = new CyclicBarrier(threadCount, () -> {
* System.out.println("All phases completed");
* });
* }
*
* public void executeComplexTask() {
* // 执行多阶段任务
* try {
* performPhase1();
* phase1Barrier.await(); // 第一阶段同步点
*
* performPhase2();
* phase2Barrier.await(); // 第二阶段同步点
*
* performCleanup();
* completionBarrier.await(); // 完成同步点
* } catch (Exception e) {
* Thread.currentThread().interrupt();
* }
* }
* }
*
* 10. 性能调优:
* // 在高并发场景下优化性能
* CyclicBarrier barrier = new CyclicBarrier(
* Runtime.getRuntime().availableProcessors(),
* () -> {
* // 轻量级的回调操作
* System.out.println("Synchronization point reached");
* }
* );
*
* // 避免在回调中执行耗时操作
* // 使用异步处理复杂逻辑
* public void asyncCallbackProcessing() {
* CyclicBarrier barrier = new CyclicBarrier(4, () -> {
* // 立即返回,异步处理复杂逻辑
* CompletableFuture.runAsync(() -> {
* // 复杂的后处理逻辑
* performComplexPostProcessing();
* });
* });
* }
*/
6. 与其他同步机制的比较
/**
* CyclicBarrier vs CountDownLatch vs Semaphore vs Phaser:
*
* CyclicBarrier:
* - 多线程相互等待到达同步点
* - 可重复使用
* - 支持回调命令
* - 适用于分阶段同步
* - 可重入性支持
*
* CountDownLatch:
* - 一次性使用,计数器只能减少
* - 一个或多个线程等待其他线程完成
* - 不支持重置
* - 适用于简单的等待/通知场景
* - 性能较好
*
* Semaphore:
* - 控制资源访问数量
* - 支持许可证的获取和释放
* - 可以动态调整许可数量
* - 适用于资源池管理
* - 支持公平性和非公平性
*
* Phaser:
* - JDK 7新增,功能最强大
* - 支持动态注册和注销参与者
* - 支持分层组织
* - 可重复使用
* - 适用于复杂的同步场景
*
* 性能对比:
* - 简单等待:CountDownLatch > CyclicBarrier > Semaphore > Phaser
* - 复杂同步:Phaser > CyclicBarrier > Semaphore > CountDownLatch
* - 内存使用:CountDownLatch < CyclicBarrier < Semaphore < Phaser
* - 功能丰富度:Phaser > CyclicBarrier > Semaphore > CountDownLatch
*
* 选择建议:
* - 简单等待多个事件完成:CountDownLatch
* - 分阶段并行计算:CyclicBarrier
* - 资源访问控制:Semaphore
* - 复杂同步需求:Phaser
* - 需要重置功能:CyclicBarrier或Phaser
* - 高性能简单场景:CountDownLatch
*
* 使用场景:
* - CyclicBarrier:分阶段并行计算、多线程协同工作
* - CountDownLatch:主线程等待子线程完成、启动门闩、关闭门闩
* - Semaphore:资源池、流量控制、连接池
* - Phaser:复杂的工作流、动态参与者管理
*
* 线程安全性:
* - 所有机制都提供完全的线程安全性
* - CyclicBarrier和Phaser支持更复杂的同步模式
* - CountDownLatch和Semaphore适用于简单的同步需求
*
* 可重用性:
* - CyclicBarrier:完全可重用
* - Phaser:完全可重用
* - CountDownLatch:一次性使用
* - Semaphore:可重用(通过acquire/release)
*/
7. 总结
CyclicBarrier 的核心特性:
-
屏障同步:
- 多个线程相互等待到达同步点
- 当所有线程都到达后,同时继续执行
- 提供分阶段同步的能力
-
可重用性:
- 屏障突破后可以重复使用
- 通过Generation机制区分不同的周期
- 支持多次同步操作
-
回调机制:
- 支持屏障突破时的回调操作
- 回调在最后一个到达线程中执行
- 提供屏障突破后的处理机会
-
状态管理:
- 使用Generation标识不同的屏障周期
- 通过broken标志管理屏障状态
- 支持屏障的破坏和重置
-
线程安全:
- 使用ReentrantLock保护临界区
- 使用Condition实现线程等待和唤醒
- 所有操作都是线程安全的
-
异常处理:
- 支持线程中断处理
- 支持超时处理
- 支持回调异常处理
- 提供详细的异常信息
-
灵活的等待机制:
- 支持无限期等待
- 支持可中断等待
- 支持超时等待
- 提供多种等待选项
-
高效的唤醒机制:
- 屏障突破时一次性唤醒所有等待线程
- 避免逐个唤醒的开销
- 提高唤醒效率
适用场景:
- 分阶段并行计算
- 多线程协同工作
- 需要同步点的场景
- 可重复使用的同步需求
- 需要回调处理的场景
- 复杂的多阶段同步
- 需要监控和诊断的场景
注意事项:
- 必须正确处理所有可能的异常
- 避免在回调命令中执行耗时操作
- 合理使用超时机制避免无限等待
- 正确处理线程中断
- 避免死锁(保持屏障获取顺序)
- 监控屏障状态和性能
- 合理设置参与线程数量
- 正确使用reset()方法
性能优化建议:
- 根据实际需求设置合适的参与线程数量
- 使用超时机制避免无限等待
- 在回调命令中执行轻量级操作
- 正确处理中断和异常
- 监控屏障的使用情况
- 避免不必要的屏障重置
- 保持一致的屏障获取顺序
- 在高并发场景下优化性能
- 使用异步处理复杂回调逻辑
- 定期分析和调优同步性能

166

被折叠的 条评论
为什么被折叠?



