[JDK源码]J.U.C-CyclicBarrier

本文详细解析了CyclicBarrier,一种Java并发工具,它用于在线程间同步,确保所有线程到达后才继续执行。讲解了其构造器、await原理、reset操作,以及如何在多线程中实现线程间的有序协作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CyclicBarrier原理

CyclicBarrier :屏障 需要等到所有的线程必须都到达之后,才能继续执行。

就是 parties 变量 如果是5 的话 就相当于 来人拦住他 够5个了 放行。

屏障的每次使用都表示为一个生成实例。 每当屏障被触发或重置时,生成就会改变。 由于锁的不确定性方式,可能有许多代与使用该障碍的线程相关联 可以分配给等待的线程——但是在同一时间只有一个线程是活动的({@code count}应用的线程),其余的线程要么被破坏要么被触发。 如果有断点但没有后续重置,则不需要有活动生成。

核心与构造器

public class CyclicBarrier {
    //用于 reset方法后复用,
	private static class Generation {
        boolean broken = false;// 当前 有没有被强制中断
    }
    private final ReentrantLock lock = new ReentrantLock();
    //阻塞线程的条件变量 
    private final Condition trip = lock.newCondition();
    //参与的线程数 (拦截的线程数)
    private final int parties;
    // 当前线程都参与了  后回调的方法
    private final Runnable barrierCommand;
    // 当前 这一代
    private Generation generation = new Generation();
    //还未到的  线程数
    private int count;


	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);
    }
}

await原理

//awati() 方法  调 dowait()方法
public int await() throws InterruptedException, BrokenBarrierException {
    try {
        return dowait(false, 0L);
    } catch (TimeoutException toe) {
        throw new Error(toe); // cannot happen
    }
}
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();
		//线程中断,		此时并没有改变这一代 的Generation
        if (Thread.interrupted()) {
            breakBarrier();
            throw new InterruptedException();
        }

        int index = --count;
        if (index == 0) { // 最后一个到达这一代的线程,负责唤醒所有阻塞在条件变量上的线程
        //然后回调barrierCommand
            boolean ranAction = false;
            try {
                final Runnable command = barrierCommand;
                if (command != null)
                    command.run();
                ranAction = true;
                nextGeneration();// 进入下一代
                return 0;
            } finally {// barrierCommand回调方法发生了异常,那么设置broken标志位
                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();
    }
}

dowait方法,每次都将count-1,减完之后判断是否等于0,等于0的话就会执行之前指定好的认为u,执行完成后 调用nextGeneration方法 进入下一代,该方法讲所有线程唤醒,将计数器的值重新设置。在执行完nextGeneration()方法就是说 此场结束。

如果计数器此时还不等于0 ,for循环 根据传入的参数来决定 定时等待还是非定时等待 ,如果在等待过程中线程中断 执行 breakBarrier()方法,意味着中途打断设置 generation的broken状态为 true 并唤醒所有线程。

private void nextGeneration() {//切换到下一代
    // 唤醒所有线程
    trip.signalAll();
    // 重新设置 计数器的值
    count = parties;
    //重新设置 代
    generation = new Generation();
}
//中途打断设置
private void breakBarrier() {
    generation.broken = true;//设置为中断状态
    count = parties;//重新设置 count
    trip.signalAll();//唤醒全部等待线程
}
private void nextGeneration() {
    // 唤醒
    trip.signalAll();
    // 重新设置
    count = parties;
    generation = new Generation();//重置
}

reset原理

public void reset() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        breakBarrier();   // 将所有参与的  线程唤醒
        nextGeneration(); // 开始新一代
    } finally {
        lock.unlock();
    }
}
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值