Java での CyclicBarrier ソース コード分析

WBOY
リリース: 2023-04-30 20:55:13
転載
1359 人が閲覧しました

    CyclicBarrier の概要

    CountDownLatch の場合、他のスレッドはリーグ オブ レジェンドなどのゲーム プレーヤーであり、メイン スレッドはゲームの開始を制御するスレッド。すべてのプレイヤーの準備が整う前に、メインスレッドは待機状態になります。これは、ゲームを開始できないことを意味します。すべてのプレイヤーの準備が整うと、次のアクション実行者がメインスレッドとなり、ゲームが開始されます。

    CyclicBarrier について、会社が全従業員にチームビルディング活動を実施させたいとします。活動内容は 3 つの障害物を登るというもので、各人が障害物を登るのにかかる時間は異なります。ただし、会社では、全員が次の障害物を乗り越え始める前に、現在の障害物を乗り越えることを要求しています。つまり、全員が最初の障害物を乗り越えた後、2 番目の障害物を乗り越え始めます。たとえて言えば、すべての従業員は「他のスレッド」です。全員がすべての障害を乗り越えると、プログラムは終了します。メインスレッドはずっと前に終了している可能性があるため、ここではメインスレッドについて心配する必要はありません。

    CyclicBarrier ソース コード分析

    クラス継承関係

    CyclicBarrier は、どの親クラスを継承するか、どの親インターフェイスを実装するかを示しません。すべての AQS およびリエントラント ロックは、継承は組み合わせによって実現されます。

    public class CyclicBarrier {}
    ```  
    
    ### 类的内部类
    
    CyclicBarrier类存在一个内部类Generation,每一次使用的CycBarrier可以当成Generation的实例,其源代码如下
    
    ```java
    private static class Generation {
    boolean broken = false;
    }
    ログイン後にコピー

    説明: Generation クラスには、現在のバリアが損傷しているかどうかを示すために使用される属性 Broker があります。

    クラス属性

    public class CyclicBarrier {
    
    /** The lock for guarding barrier entry */
    // 可重入锁
    private final ReentrantLock lock = new ReentrantLock();
    /** Condition to wait on until tripped */
    // 条件队列
    private final Condition trip = lock.newCondition();
    /** The number of parties */
    // 参与的线程数量
    private final int parties;
    /* The command to run when tripped */
    // 由最后一个进入 barrier 的线程执行的操作
    private final Runnable barrierCommand;
    /** The current generation */
    // 当前代
    private Generation generation = new Generation();
    // 正在等待进入屏障的线程数量
    private int count;
    }
    ログイン後にコピー

    説明: この属性には ReentrantLock オブジェクトと Condition オブジェクトがあり、Condition オブジェクトは AQS に基づいているため、最終的な分析では、最下層は引き続き AQS によってサポートされています。

    クラス コンストラクター

    CyclicBarrier(int, Runnable) 型コンストラクター

    public CyclicBarrier(int parties, Runnable barrierAction) {
    // 参与的线程数量小于等于0,抛出异常
    if (parties <= 0) throw new IllegalArgumentException();
    // 设置parties
    this.parties = parties;
    // 设置count
    this.count = parties;
    // 设置barrierCommand
    this.barrierCommand = barrierAction;
    }
    ログイン後にコピー

    説明: Thisコンストラクターでは、CyclicBarrier に関連付けられたスレッドの数を指定でき、すべてのスレッドがバリアに入った後の実行アクションを指定できます。実行アクションは、バリアを実行する最後のスレッドによって実行されます。

    CyclicBarrier(int) 型コンストラクター

    public CyclicBarrier(int parties) {
    // 调用含有两个参数的构造函数
    this(parties, null);
    }
    ログイン後にコピー

    説明: このコンストラクターは、CyclicBarrier に関連付けられた関数のみを実行します。スレッドの数に応じて、実行アクションは設定されません。

    コア関数 - dowait 関数

    この関数は CyclicBarrier クラスのコア関数であり、CyclicBarrier クラスが提供する await 関数は最下層の doawait 関数を呼び出します。

    ソース コードは次のとおりです。

    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) { // 正在等待进入屏障的线程数量为0,所有线程都已经进入
    // 运行的动作标识
    boolean ranAction = false;
    try {
    // 保存运行动作
    final Runnable command = barrierCommand;
    if (command != null) // 动作不为空
    // 运行
    command.run();
    // 设置ranAction状态
    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) // 设置了等待时间,并且等待时间大于0
    // 等待指定时长
    nanos = trip.awaitNanos(nanos);
    } catch (InterruptedException ie) {
    if (g == generation && ! g.broken) { // 等于当前代并且屏障没有被损坏
    // 损坏当前屏障
    breakBarrier();
    // 抛出异常
    throw ie;
    } else { // 不等于当前带后者是屏障被损坏
    // We&#39;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) { // 设置了等待时间,并且等待时间小于0
    // 损坏屏障
    breakBarrier();
    // 抛出异常
    throw new TimeoutException();
    }
    }
    } finally {
    // 释放锁
    lock.unlock();
    }
    }
    ログイン後にコピー

    コア関数-nextGeneration 関数

    この関数は、すべてのスレッドがバリアに入った後に呼び出されます。次のバージョンが生成され、すべてのスレッドがバリアに再度入ることができます。

    ソース コードは次のとおりです:

    private void nextGeneration() {
    // signal completion of last generation
    // 唤醒所有线程
    trip.signalAll();
    // set up next generation
    // 恢复正在等待进入屏障的线程数量
    count = parties;
    // 新生一代
    generation = new Generation();
    }
    ログイン後にコピー

    この関数では、signalAll メソッドAQS が呼び出され、待機中のすべてのスレッドが起動されます。すべてのスレッドがこの状態を待っている場合は、すべてのスレッドを起動します。

    ソースコードは次のとおりです:

    public final void signalAll() {
    if (!isHeldExclusively()) // 不被当前线程独占,抛出异常
    throw new IllegalMonitorStateException();
    // 保存condition队列头节点
    Node first = firstWaiter;
    if (first != null) // 头节点不为空
    // 唤醒所有等待线程
    doSignalAll(first);
    }
    ログイン後にコピー

    以上がJava での CyclicBarrier ソース コード分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

    関連ラベル:
    ソース:yisu.com
    このウェブサイトの声明
    この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
    人気のチュートリアル
    詳細>
    最新のダウンロード
    詳細>
    ウェブエフェクト
    公式サイト
    サイト素材
    フロントエンドテンプレート