CyclicBarrier源码浅析

目录

简述

成员变量

等待解除阻塞

重置

获取当前阻塞的线程个数


简述

阻塞多个线程,直到阻塞的线程个数达到一定条件,则唤醒所有阻塞的线程,并由唤醒的线程执行任务。

 

成员变量

    // 用于线程安全的锁
    private final ReentrantLock lock = new ReentrantLock();
    // 等待条件
    private final Condition trip = lock.newCondition();
    // 需要触发解除阻塞的线程总数
    private final int parties;
    // 解除阻塞时运行的任务
    private final Runnable barrierCommand;
    /** The current generation */
    private Generation generation = new Generation();
    // 用于记录当前剩余触发解除线程阻塞的个数
    private int count;

 

等待解除阻塞

    public int await() throws InterruptedException, BrokenBarrierException {
        try {
            return dowait(false, 0L);
        } catch (TimeoutException toe) {
            throw new Error(toe); // cannot happen
        }
    }

    public int await(long timeout, TimeUnit unit)
        throws InterruptedException,
               BrokenBarrierException,
               TimeoutException {
        return dowait(true, unit.toNanos(timeout));
    }

 

dowait方法

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

	    // 更新count
            int index = --count;
			
	    // 如果当前调用await方法的线程个数满足count,执行barrierCommand任务,并唤醒所有等待的线程
            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 {
                        // We're about to finish waiting even if we had not
                        // been interrupted, so this interrupt is deemed to
                        // "belong" to subsequent execution.
                        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(); // 解锁
        }
    }

    private void nextGeneration() {
        // signal completion of last generation
	// 唤醒所有等待的线程
        trip.signalAll();
        // set up next generation
	// 重置count
        count = parties;
        generation = new Generation();
    }

 

重置

    public void reset() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            breakBarrier();   // break the current generation
            nextGeneration(); // start a new generation
        } finally {
            lock.unlock();
        }
    }

 

获取当前阻塞的线程个数

    public int getNumberWaiting() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            return parties - count;
        } finally {
            lock.unlock();
        }
    }

 

### Java `CyclicBarrier` 源码解析 #### 类定义与字段解释 `CyclicBarrier` 是一个同步辅助类,它允许一组线程互相等待直至全部线程均抵达某个共同的屏障点。一旦所有参与方均已就位,则它们会一同继续执行下去[^3]。 ```java public class CyclicBarrier { final ReentrantLock lock = new ReentrantLock(); final Condition trip = lock.newCondition(); private final int parties; private final Runnable barrierCommand; private Generation generation = new Generation(); /** The current number of parties waiting in await(), minus count */ private int count; // Internal helper class to manage state. private static class Generation { boolean broken = false; } } ``` 这段代码展示了 `CyclicBarrier` 的主要成员变量: - `ReentrantLock lock`: 提供独占锁机制用于保护共享资源访问。 - `Condition trip`: 条件队列用来挂起和唤醒等待中的线程。 - `int parties`: 表明有多少个参与者需要达到屏障才能触发释放操作。 - `Runnable barrierCommand`: 当所有线程到达屏障后可以执行的一次性任务。 - `Generation generation`: 记录当前代的状态信息,包括是否已破损。 #### 构造函数初始化 创建一个新的 `CyclicBarrier` 实例时可以选择指定一个动作作为最后一名加入者完成注册后的回调处理程序。 ```java /** * Creates a new {@code CyclicBarrier} that will trip when the given * number of parties (threads) are awaiting upon it, and which executes * the given command when tripped. * * @param parties the number of threads that must invoke {@link #await()} * before the barrier is tripped * @param barrierCommand the command to execute once all threads have become * ready but before any are released; or null if no action should be performed * @throws IllegalArgumentException if {@code parties <= 0} */ public CyclicBarrier(int parties, Runnable barrierCommand) { if (parties <= 0) throw new IllegalArgumentException(); this.parties = parties; this.count = parties; this.barrierCommand = barrierCommand; } // Convenience constructor with default behavior on trip public CyclicBarrier(int parties) { this(parties, null); } ``` #### 主要方法剖析 ##### 方法:`await()` 此方法使调用它的线程进入休眠状态直到其他所有预定数量的线程也完成了各自的 `await()` 调用为止;如果发生异常情况(比如超时或被中断),则整个障碍会被标记为破坏并抛出相应类型的异常给各个等待着的线程。 ```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(); } 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 { // We're about to finish anyway Thread.currentThread().interrupt(); } } catch (TimeoutException toe) { if (g == generation) { breakBarrier(); throw toe; } else { return index; } } if (g.broken) throw new BrokenBarrierException(); if (g != generation) return index; if (timed && nanos <= 0L) { breakBarrier(); throw new TimeoutException(); } } } finally { lock.unlock(); } } public int await() throws InterruptedException, BrokenBarrierException { try { return dowait(false, 0L); } catch (TimeoutException toe) { throw new Error(toe); // cannot happen } } public int await(long timeout, TimeUnit unit) throws InterruptedException, BrokenBarrierException, TimeoutException { return dowait(true, unit.toNanos(timeout)); } ``` 上述逻辑实现了核心功能,即让线程暂停并在满足条件时重新启动。每当有新线程调用了 `await()` 后计数器减一,当计数值降为零意味着达到了设定好的数目从而激活后续流程控制语句。 ##### 辅助方法:`nextGeneration()` 负责重置内部状态以便下一轮循环使用。 ```java private void nextGeneration() { // signal completion of last generation trip.signalAll(); // set up next generation count = parties; generation = new Generation(); } ``` ##### 错误处理:`breakBarrier()` 当遇到不可恢复错误的情况下调用此方法来通知所有等待中的线程停止工作。 ```java private void breakBarrier() { generation.broken = true; count = parties; trip.signalAll(); } ``` 通过以上介绍可以看出,`CyclicBarrier` 设计精巧地利用了锁机制以及条件变量配合实现了多线程间的协作模式,并提供了灵活易用API接口方便开发者构建复杂的应用场景下的并发结构[^2].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值