CyclicBarrier 源码

成员变量

java 复制代码
// 独占可重入锁,所有操作加锁保证线程安全
private final ReentrantLock lock = new ReentrantLock();
// 条件变量,所有到达栅栏的线程阻塞在此
private final Condition trip = lock.newCondition();
// 总等待线程数(固定不变,final)
private final int parties;
// 最后一个线程到达时执行的回调任务
private final Runnable barrierCommand;
// 当前代次实例
private Generation generation = new Generation();
// 当前剩余等待线程数(每轮从parties递减到0)
private int count;

构造方法

java 复制代码
// 带屏障任务
public CyclicBarrier(int parties, Runnable barrierAction) {
    if (parties <= 0) throw new IllegalArgumentException();
    this.parties = parties;
    this.count = parties;
    this.barrierCommand = barrierAction;
}

// 无屏障任务,委托上面构造器
public CyclicBarrier(int parties) {
    this(parties, null);
}

Generation

java 复制代码
private static class Generation {
    boolean broken = false; // true=本轮栅栏损坏
}

await

java 复制代码
public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        throw new Error(toe); // timed=false不会触发超时,不可能走到这里
    }
}

dowait

java 复制代码
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();
        }
			
		// 等待计数-1,index是当前线程到达序号(最后一个为0)
        int index = --count;
        // 所有线程全部抵达,触发栅栏
        if (index == 0) {  // tripped
            boolean ranAction = false;
            try {
                final Runnable command = barrierCommand;
                if (command != null)
                    command.run();
                ranAction = true;
                // 重置栅栏,开启下一轮
                nextGeneration();
                return 0;
            } finally {
                if (!ranAction)
                    breakBarrier(); // 屏障任务执行异常,栅栏损坏
            }
        }

        // loop until tripped, broken, interrupted, or timed out
        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)
           		// 代次更新,说明本次 count 已经为 0,栅栏放行,返回序号
                return index;

            if (timed && nanos <= 0L) {
            	// 超时未集齐线程,破坏栅栏抛超时异常
                breakBarrier();
                throw new TimeoutException();
            }
        }
    } finally {
        lock.unlock();
    }
}

nextGeneration

java 复制代码
private void nextGeneration() {
    // 1. 唤醒当前代所有阻塞在trip条件队列的线程
    trip.signalAll();
    // 2. 重置等待计数器为初始总线程数
    count = parties;
    // 3. 新建Generation实例,切换到全新一代,旧代作废
    generation = new Generation();
}

breakBarrier

java 复制代码
private void breakBarrier() {
    // 1. 标记当前代栅栏损坏
    generation.broken = true;
    // 2. 重置计数器
    count = parties;
    // 3. 唤醒所有等待线程
    trip.signalAll();
}

总结

plaintext 复制代码
线程调用 barrier.await()
        ↓
dowait(timed=false, nanos=0)
        ↓
lock.lock() → 抢占独占锁
        ↓
读取当前代 Generation g = generation
        ├─ if g.broken → 抛 BrokenBarrierException,finally释放锁
        └─ 校验当前线程是否中断 Thread.interrupted()
                ├─ 是 → breakBarrier() + 抛 InterruptedException,释放锁
                └─ 否 → count = count - 1,得到当前index
                        ├─────────────────────┬
                        ↓                     ↓
                index == 0(最后线程)    index != 0(普通等待线程)
                        ↓                     ↓
                执行 barrierCommand       进入 for(;;) 循环阻塞
                        │                     │
                        │                     │→ trip.await()
                        │                     │
                        │                     ↓(被signalAll唤醒后)重新竞争lock锁
                        │                     │
                        │                     ├─ g != generation → 正常return index
                        ↓
                任务执行成功 → nextGeneration()
                        │        ↓
                        │        trip.signalAll() 唤醒所有条件队列线程
                        │        count重置为parties
                        │        new Generation() 切换代次
                        ↓
                finally 释放锁 lock.unlock()
相关推荐
2301_32241428041 天前
基于SpringBoot+Vue的休闲零食超市管理系统的设计与实现59004-计算机毕设 原创(免费领源码+部署教程+开发环境)
java·vue.js·spring boot·redis·mysql·决策树·推荐算法
徐小夕1 天前
花了3个月,我们做了一款 AI 版的“飞书文档”
前端·算法·github
Robert--cao1 天前
移动底盘与机械臂联合规划:开源算法与工程实现
算法
金銀銅鐵1 天前
[Java] 用 GUI 展示 EnumSet 增减元素时的内部变化(上)
java·后端·ai编程
福建佰胜张工1 天前
SMC 薄型气爪 MHF2-16D1 深度解析:平行开闭、低剖面结构在自动化装配中的选型与落地
java·服务器·安全·自动化
小豆庄1 天前
Mac 上给视频人脸打码:本地工具的依赖、追踪与推理管线
算法·视觉检测·视频·敏捷流程·纹理贴图
catoop1 天前
API Key 设计与安全生成方案:结构拆解、数据库设计与 Java 实现
java·数据库·安全
星夜离尘561 天前
MATLAB 工程实验:从相邻块均值手写重叠 Allan 偏差,数清有效项
算法·matlab·均值算法
system_error_x1 天前
SpringBoot 集成 Thymeleaf 简洁入门
java·spring boot·后端
驭渊的小故事1 天前
Spring AI Alibaba 实战:从maven依赖治理到声明式工具调用
java·人工智能·spring