173

java.util.concurrent APIを読んでいたところ、

  • CountDownLatch:他のスレッドで実行されている一連の操作が完了するまで、1つ以上のスレッドが待機できるようにする同期支援。
  • CyclicBarrier:一連のスレッドが互いに共通のバリアポイントに到達するのをすべて待機できるようにする同期支援。

私には両方とも同じように見えますが、それ以上のものがあると確信しています。

たとえば、CoundownLatch, the countdown value could not be reset, that can happen in the case of CyclicBarrier

2つの間に他の違いはありますか?誰かがカウントダウンの値をリセットしたい場所はどこですか
use cases

4

14 に答える 14

145

もう一つ違いがあります。

を使用する場合CyclicBarrier、バリアをトリガーする待機中のスレッドの数を指定することを前提としています。5 を指定する場合、呼び出すスレッドが少なくとも 5 つ必要ですawait()

を使用する場合は、待機中のすべてのスレッドが解放されるCountDownLatchの呼び出し回数を指定します。これは、 を1 つのスレッドでのみcountDown()使用できることを意味します。CountDownLatch

「どうしてそんなことをするの?」とあなたは言うかもしれません。コールバックを実行する、他の誰かによってコード化された謎の API を使用していると想像してください。特定のコールバックが何度も呼び出されるまで、スレッドの 1 つを待機させたいとします。コールバックが呼び出されるスレッドはわかりません。この場合、 aCountDownLatchは完璧ですが、 a を使用してこれを実装する方法は考えられませんCyclicBarrier(実際にはできますが、タイムアウトが発生します... うん!)。

CountDownLatchリセットできればいいのに!

于 2011-03-01T04:53:33.413 に答える
144

主な違いの 1 つは、CyclicBarrierが、共通のバリア条件が満たされると実行される (オプションの) Runnable タスクを取ることです。

また、バリアで待機しているクライアントの数と、バリアをトリガーするために必要な数を取得することもできます。トリガーされると、バリアはリセットされ、再び使用できるようになります。

単純な使用例 (サービスの開始など) の場合、CountdownLatch は問題ありません。CyclicBarrier は、より複雑な調整タスクに役立ちます。そのようなことの例は、並列計算です - 複数のサブタスクが計算に関与する場合 - MapReduceのようなものです。

于 2010-11-12T20:37:32.530 に答える
48

誰もまだ言及していない点の 1 つは、aCyclicBarrierでは、スレッドに問題 (タイムアウト、中断など) がある場合、到達した他のすべてのスレッドでawait()例外が発生するということです。Javadoc を参照してください。

CyclicBarrier は、失敗した同期試行に対して全か無かの破損モデルを使用します。スレッドが中断、失敗、またはタイムアウトのために時期尚早にバリア ポイントを離れた場合、そのバリア ポイントで待機している他のすべてのスレッドも、BrokenBarrierException (または InterruptedException) を介して異常に終了します。それらもほぼ同時に中断された場合)。

于 2012-10-07T16:03:02.503 に答える
25

JavaDoc で違いが明確に説明されていると思います。ほとんどの人は、CountDownLatch がリセットできないことを知っていますが、CyclicBarrier はリセットできます。ただし、違いはこれだけではありません。CyclicBarrier の名前を ResetbleCountDownLatch に変更することもできます。JavaDoc に記述されている目標の観点から違いを伝える必要があります。

CountDownLatch: 1 つまたは複数のスレッドが、他のスレッドで実行されている一連の操作が完了するまで待機できるようにする同期支援。

CyclicBarrier:一連のスレッドがすべて互いに共通のバリア ポイントに到達するのを待機できるようにする同期支援。

countDownLatch には、他のスレッドのセットが完了するのを待っている 1 つ以上のスレッドがあります。この状況では、スレッドには 2 種類あります。1 つは待機中、もう 1 つは何かを実行中です。タスクの完了後、待機中または終了したばかりの可能性があります。

CyclicBarrier では、スレッドの種類は 1 つだけで、互いに待機しており、同等です。

于 2014-07-02T06:33:50.087 に答える
14

主な違いは、CountdownLatchのJavadocに記載されています。すなわち:

CountDownLatchは、指定されたカウントで初期化されます。countDown()メソッドの呼び出しにより、現在のカウントがゼロに達するまでawaitメソッドはブロックされます。その後、すべての待機中のスレッドが解放され、その後のawaitの呼び出しはすぐに返されます。これは一発の現象であり、カウントをリセットすることはできません。カウントをリセットするバージョンが必要な場合は、CyclicBarrierの使用を検討してください。

ソース1.6Javadoc

于 2010-11-12T20:44:11.653 に答える
12

CountDownLatch は、1 回限りの同期に使用されます。CountDownLatch を使用している間、スレッドは countDown() を何度でも呼び出すことができます。await() を呼び出したスレッドは、ブロックされていない他のスレッドによる countDown() の呼び出しにより、カウントがゼロになるまでブロックされます。CountDownLatchのJavadoc には次のように記載されています。

await メソッドは、countDown() メソッドの呼び出しによって現在のカウントがゼロになるまでブロックします。その後、待機中のすべてのスレッドが解放され、後続の await の呼び出しはすぐに戻ります。...

もう 1 つの典型的な使用法は、問題を N 個の部分に分割し、その部分を実行してラッチをカウントダウンする Runnable で各部分を記述し、すべての Runnable を Executor にキューに入れることです。すべてのサブパートが完了すると、調整スレッドは await を通過できるようになります。(スレッドがこのように繰り返しカウントダウンする必要がある場合は、代わりに CyclicBarrier を使用してください。)

対照的に、サイクリック バリアは複数の同期ポイントに使用されます。たとえば、一連のスレッドがループ/フェーズ計算を実行しており、次の反復/フェーズを開始する前に同期する必要がある場合などです。CyclicBarrierのjavadocによると:

バリアは、待機中のスレッドが解放された後に再利用できるため、サイクリックと呼ばれます。

CountDownLatch とは異なり、await() への各呼び出しはいくつかのフェーズに属し、そのフェーズに属するすべての関係者が await() を呼び出すまで、スレッドをブロックさせることができます。CyclicBarrier でサポートされている明示的な countDown() 操作はありません。

于 2012-04-30T02:02:22.750 に答える
12

この質問はすでに十分に回答されていますが、コードを投稿することで少し付加価値を付けることができると思います。

サイクリック バリアの動作を説明するために、いくつかのサンプル コードを作成しました。バリアが傾くとすぐに、再び使用できるように自動的にリセットされます (したがって、「周期的」です)。プログラムを実行すると、バリアが傾いた後にのみ「Let's play」という出力がトリガーされることに注意してください。

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class CyclicBarrierCycles {

    static CyclicBarrier barrier;

    public static void main(String[] args) throws InterruptedException {
        barrier = new CyclicBarrier(3); 

        new Worker().start();
        Thread.sleep(1000);
        new Worker().start();
        Thread.sleep(1000);
        new Worker().start();
        Thread.sleep(1000);

        System.out.println("Barrier automatically resets.");

        new Worker().start();
        Thread.sleep(1000);
        new Worker().start();
        Thread.sleep(1000);
        new Worker().start();
    }

}


class Worker extends Thread {
    @Override
    public void run() {
        try {
            CyclicBarrierCycles.barrier.await();
            System.out.println("Let's play.");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (BrokenBarrierException e) {
            e.printStackTrace();
        }
    }
}
于 2014-04-12T06:24:56.657 に答える
5

明らかな違いの 1 つは、N の CyclicBarrier が 1 サイクルで解放されるのを待機できるのは、N スレッドだけであるということです。ただし、N の CountDownLatch で待機できるスレッドの数に制限はありません。カウント ダウンのデクリメントは、1 つのスレッドで N 回、または N スレッドでそれぞれ 1 回、または組み合わせて行うことができます。

于 2015-10-29T17:21:07.197 に答える
4

CyclicBarrier の場合、すべての子スレッドが barrier.await() の呼び出しを開始するとすぐに、Runnable が Barrier で実行されます。各子スレッドの barrier.await が完了するまでにかかる時間は異なり、それらはすべて同時に完了します。

于 2011-12-14T14:58:06.053 に答える