Java concurrency: Countdown latch vs Cyclic barrier

前端 未结 14 1922
隐瞒了意图╮
隐瞒了意图╮ 2020-11-29 14:44

I was reading through the java.util.concurrent API, and found that

  • CountDownLatch: A synchronization aid that allows one or more threads to wait
相关标签:
14条回答
  • 2020-11-29 15:17

    I think that the JavaDoc has explained the differences explicitly. Most people know that CountDownLatch can not be reset, however, CyclicBarrier can. But this is not the only difference, or the CyclicBarrier could be renamed to ResetbleCountDownLatch. We should tell the differences from the perspective of their goals, which are described in JavaDoc

    CountDownLatch: A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.

    CyclicBarrier: A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.

    In countDownLatch, there is one or more threads, that are waiting for a set of other threads to complete. In this situation, there are two types of threads, one type is waiting, another type is doing something, after finishes their tasks, they could be waiting or just terminated.

    In CyclicBarrier, there are only one type of threads, they are waiting for each other, they are equal.

    0 讨论(0)
  • 2020-11-29 15:19

    One major difference is that CyclicBarrier takes an (optional) Runnable task which is run once the common barrier condition is met.

    It also allows you to get the number of clients waiting at the barrier and the number required to trigger the barrier. Once triggered the barrier is reset and can be used again.

    For simple use cases - services starting etc... a CountdownLatch is fine. A CyclicBarrier is useful for more complex co-ordination tasks. An example of such a thing would be parallel computation - where multiple subtasks are involved in the computation - kind of like MapReduce.

    0 讨论(0)
  • 2020-11-29 15:22

    This question has been adequately answered already, but I think I can value-add a little by posting some code.

    To illustrate the behaviour of cyclic barrier, I have made some sample code. As soon as the barrier is tipped, it is automatically reset so that it can be used again (hence it is "cyclic"). When you run the program, observe that the print outs "Let's play" are triggered only after the barrier is tipped.

    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();
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-29 15:25

    CountDownLatch is a count down of anything; CyclicBarrier is a count down for thread only

    assume there are 5 worker threads and one shipper thread, and when workers produce 100 items, shipper will ship them out.

    For CountDownLatch, the counter can be on workers or items

    For CyclicBarrier, the counter can only on workers

    If a worker falls infinite sleep, with CountDownLatch on items, Shipper can ship; However, with CyclicBarrier, Shipper can never be called

    0 讨论(0)
  • 2020-11-29 15:26

    One point that nobody has yet mentioned is that, in a CyclicBarrier, if a thread has a problem (timeout, interrupted...), all the others that have reached await() get an exception. See Javadoc:

    The CyclicBarrier uses an all-or-none breakage model for failed synchronization attempts: If a thread leaves a barrier point prematurely because of interruption, failure, or timeout, all other threads waiting at that barrier point will also leave abnormally via BrokenBarrierException (or InterruptedException if they too were interrupted at about the same time).

    0 讨论(0)
  • 2020-11-29 15:26

    A CountDownLatch is used for one-time synchronization. While using a CountDownLatch, any thread is allowed to call countDown() as many times as they like. Threads which called await() are blocked until the count reaches zero because of calls to countDown() by other unblocked threads. The javadoc for CountDownLatch states:

    The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. ...

    Another typical usage would be to divide a problem into N parts, describe each part with a Runnable that executes that portion and counts down on the latch, and queue all the Runnables to an Executor. When all sub-parts are complete, the coordinating thread will be able to pass through await. (When threads must repeatedly count down in this way, instead use a CyclicBarrier.)

    In contrast, the cyclic barrier is used for multiple sychronization points, e.g. if a set of threads are running a loop/phased computation and need to synchronize before starting the next iteration/phase. As per the javadoc for CyclicBarrier:

    The barrier is called cyclic because it can be re-used after the waiting threads are released.

    Unlike the CountDownLatch, each call to await() belongs to some phase and can cause the thread to block until all parties belonging to that phase have invoked await(). There is no explicit countDown() operation supported by the CyclicBarrier.

    0 讨论(0)
提交回复
热议问题