Real Life Examples For CountDownLatch and CyclicBarrier
Asked Answered
T

13

43

One example is given by one of our trainers when he was explaining difference between CountDownLatch and CyclicBarrier.

CountDownLatch: Suppose a stone can be lifted by 10 people so you will wait for all 10 to come. Then only you can lift the stone.

CyclicBarrier: If you are going to a picnic, and you need to first meet at some common point from where you all will start your journey.

If Anybody agrees with these comments please give me some details.

I have already read the sun API for both these classes. But I need some more explaination.

Terryterrye answered 14/4, 2012 at 18:30 Comment(7)
refer this mkorytin.blogspot.in/2011/07/… and shazsterblog.blogspot.in/2011/12/….. some very good understanding and exampleWideopen
another link that you might find useful is adnanfaizan.blogspot.in/2013/10/…Kutzer
@Sunny This is now old question but it's new for me. Can you please answer 2 questions (1). Is your Cyclic Barrier example (picnic) is correct here?? Question (2). In this Cyclic Barrier example if there are 10 people going for picnic they need to meet at some common point where all will start their journey again. Can their be multiple common points in this journey for all threads to meet before reaching to the club(or destination).Postulant
@PradeepSingh 1) the picnic example is correct 2) you can have multiple common points, you can achieve that by different instances of cyclic barrier.Terryterrye
Thanks Sunny ^_^Postulant
you can also refer this video youtube.com/watch?v=aXquiU12A4gTerryterrye
@SunnyGupta, you should always say that the video that you are linking in the comment is your own.Sardinia
V
44

The key difference is that CountDownLatch separates threads into waiters and arrivers while all threads using a CyclicBarrier perform both roles.

  • With a latch, the waiters wait for the last arriving thread to arrive, but those arriving threads don't do any waiting themselves.
  • With a barrier, all threads arrive and then wait for the last to arrive.

Your latch example implies that all ten people must wait to lift the stone together. This is not the case. A better real world example would be an exam prompter who waits patiently for each student to hand in their test. Students don't wait once they complete their exams and are free to leave. Once the last student hands in the exam (or the time limit expires), the prompter stops waiting and leaves with the tests.

Vaasa answered 14/4, 2012 at 18:51 Comment(3)
"With a latch, the waiters wait for the last arriving thread to arrive, but those arriving threads don't do any waiting themselves." As per my understanding this should not be the case. Because main thread always wait for all the thread to count down to 0. Please explain.Terryterrye
The example should be like one co-ordinator checks if 10 people are available for lifting the stone. Am i right??Terryterrye
@SAM - Incorrect, only threads that call await on the latch block until the countdown reaches zero. Threads that call countDown do not block.Vaasa
C
83

In a hypothetical theater:

  • It is called Mutex if only one person is allowed to watch the play.
  • It is called Semaphore if N number of people are allowed to watch the play. If anybody leaves the Theater during the play then other person can be allowed to watch the play.
  • It is called CountDownLatch if no one is allowed to enter until every person vacates the theater. Here each person has free will to leave the theater.
  • It is called CyclicBarrier if the play will not start until every person enters the theater. Here a showman can not start the show until all the persons enter and grab the seat. Once the play is finished the same barrier will be applied for next show.

Here, a person is a thread, a play is a resource.

Covenant answered 5/9, 2015 at 18:21 Comment(5)
It is an amazing academy-level example! Thank you very much!Frontier
@Frontier Agreed, this is great! :DStenger
Very nice example and i can remember this easily...ThanksTush
Very good exampleGabler
Great way of explaining to remember thingsBamberg
V
44

The key difference is that CountDownLatch separates threads into waiters and arrivers while all threads using a CyclicBarrier perform both roles.

  • With a latch, the waiters wait for the last arriving thread to arrive, but those arriving threads don't do any waiting themselves.
  • With a barrier, all threads arrive and then wait for the last to arrive.

Your latch example implies that all ten people must wait to lift the stone together. This is not the case. A better real world example would be an exam prompter who waits patiently for each student to hand in their test. Students don't wait once they complete their exams and are free to leave. Once the last student hands in the exam (or the time limit expires), the prompter stops waiting and leaves with the tests.

Vaasa answered 14/4, 2012 at 18:51 Comment(3)
"With a latch, the waiters wait for the last arriving thread to arrive, but those arriving threads don't do any waiting themselves." As per my understanding this should not be the case. Because main thread always wait for all the thread to count down to 0. Please explain.Terryterrye
The example should be like one co-ordinator checks if 10 people are available for lifting the stone. Am i right??Terryterrye
@SAM - Incorrect, only threads that call await on the latch block until the countdown reaches zero. Threads that call countDown do not block.Vaasa
T
24

Real World Example I can see that all the answers are actually missing a real example. As in how these classes can be used in a software realm

  1. CountDownLatch A Multithreaded download manager. The download manager will start multiple threads to download each part of the file simultaneously.(Provided the server supports multiple threads to download). Here each thread will call a countdown method of an instantiated latch. After all the threads have finished execution, the thread associated with the countdown latch will integrate the parts found in the different pieces together into one file

  2. CyclicBarrier Same scenario as above..But assume the files are downloaded from P2P. Again multiple threads downloading the pieces. But here, suppose that you want the intergity check for the downloaded pieces to be done after a particular time interval. Here cyclic barrier plays an important role. After each time interval, each thread will wait at the barrier so that thread associated with cyclibarrier can do the integrity check. This integrity check can be done multiple times thanks to CyclicBarrier

Please correct me if anything not proper.

Tradescantia answered 23/9, 2016 at 17:48 Comment(0)
B
5

Use case 1 Suppose you have split a large job into 10 small tasks, each one a thread. You have to wait for the 10 tasks' end from that threads before considering the job done.

So the main job initiator thread initializes a CountDownLatch to the number of threads used, it distributes tasks to threads and waits for the latch raises zero with await method. Each executor thread will invoke countDown at the end of its task. Finally the main thread will be waken when all threads have finished so it considers the whole job is done. This scenario uses the doneSignal latch describes in the CountDownLatch javadoc.

Use case 2 Suppose you have split a large job into a n * m tasks, distributed over n threads. m corresponds to a matrix row and you have a total to compute for each row. In that case, threads must be synchronized after each task ending so that the total for the row is processed. In that case, a CyclicBarrier initialized with the number of threads n is used to wait for the end of each row computation (m times in fact).

To compare both, the CountDownLatch is supposed to be used only 1 time and a CyclicBarrier can be used as many times as the algorithm requires a synchronization point for a set of threads.

Bromberg answered 14/4, 2012 at 18:48 Comment(0)
R
4

A CyclicBarrier is reusable, so it's more like a racing tour where everyone meets at a waypoint before proceeding on the next leg of the tour.

Rauwolfia answered 14/4, 2012 at 18:52 Comment(1)
A CountDownLatch example is discussed here.Rauwolfia
D
4

CountDownLatch: If we want all of our threads to do

something + countdown

so that other waiting (for count to reach zero) threads can proceed, we can use countdown latch. All prior threads who actually did the countdown can go on in this situation but there is no guarantee that line processed after latch.countdown() will be after waiting for other threads to reach at latch.countdown() but it has a guarantee that other waiting threads will only start further after latch.await() has reached zero.

CyclicBarrier: If we want all our thread to

do something + await at common point + do something

(each await call will decrease wait time for threads to carry on further)

CyclicBarrier functionality can be achieved by CountDownLatch only once by calling latch.countdown() followed by latch.await() by all the threads.

but again you cant reset/reuse the countdownlatch.

Best example where I used CyclicBarrier is to initialize multiple caches (warmed by multiple threads) and then starting further processing, and I wanted to reinitialize other caches again in Sync.

Decemvirate answered 10/10, 2013 at 14:55 Comment(0)
T
4

Theoretical Difference:

In CountDownLatch, main threads waits for other threads to complete their execution. In CyclicBarrier, worker threads wait for each other to complete their execution.

You can not reuse same CountDownLatch instance once count reaches to zero and latch is open, on the other hand CyclicBarrier can be reused by resetting Barrier, Once barrier is broken.

Real life example:--

CountDownLatch: Consider a IT world scenario where manager divided modules between development teams (A and B) and he wants to assign it to QA team for testing only when both the teams completes their task.

Here manager thread works as main thread and development team works as worker thread. Manager thread waits for development teams thread to complete their task.

CyclicBarrier: Consider the same IT world scenario where manager divided modules between development teams (A and B). He goes on leave and asked both team to wait for each other to complete their respective task once both are done assign it to QA team for testing.

Here manager thread works as main thread and development team works as worker thread. Development team threads wait for other development team threads after completing their task.

Tymon answered 14/5, 2016 at 18:55 Comment(0)
D
2

For the CyclicBarrier, One real time example that I could think of; Lets imagine there is a group of tourists on a tempo traveller. There are multiple places that are to be visited in a day. The tempo driver knows there are x number of tourists. Once the first location is reached, all the tourists go out and return back at different points of time; however the tempo and the travellers have to wait until all tourists return back. Once all of them return the driver proceeds to the next location and the same process repeats. Here, the CyclicBarrier is initialized with the number of tourists. Each tourist is like a Thread and upon returning back, they call CyclicBarrier await() so that they wait until all other tourists are back. Let me now what you think

Danner answered 6/4, 2020 at 15:46 Comment(0)
C
2

CyclicBarrier: In Ludo Game APP, we cant start the game of four players until all players have joined the game. Let's assume all four players as a separate thread. in this case, a player(thread) must have to wait for all other threads(players) to join the game. Each thread will call await() method after joining the game. They can continue with their execution only after await() method is called by a defined number of threads. i.e all players joined the game.

CountDownLatch: In an IT Company Lets say there is a survey going on for a team of four members and manager need to submit the feedback of all employee to higher management. In this scenario, all four employees are threads who will give their feedback and call countDown() method. Until and unless all employees are not submitting their feedback or the deadline is reached manager thread must wait by calling await() method. After getting feedback from employees, the manager can submit the feedback to higher management. in the case of countDownLatch threads do not require waiting for each other and they can continue with their execution after calling countDown() method. i.e employees can continue to write the program or can go for lunch after submitting their feedback.

click here for more details

Choriamb answered 25/8, 2021 at 10:49 Comment(0)
B
1

A cyclic barrier as the name suggests can be used in cycles. For ex: I am a company hr looking for N number of resumes from various job portal feeds. I have a skillset array containing skills sorted in order of priority. For ex java,c#,python. I want to find N resumes matching java skillset, but if I dont find the required no. of resumes, I search again on the next skillset and so on.

I create a worker each of which scans through the resumes, in the assigned job feeds. Both workers will start with the primary skillset search in their job feeds.

After performing the search worker will check if the N resumes were found. If found, the worker will reset the barrier and return. Else it will wait for the other worker to complete. If still N resumes were not found, the search would be resumed again, on the next skill in the skillset array. So, search can be called recursively/cyclicly without needing to create a new cyclic barrier.

Baroja answered 2/2, 2018 at 15:31 Comment(0)
J
1

CountDownLatch vs CyclicBarrier

Concept

We have a roller coaster with a waiting line. Only one person can enter the roller coaster car at a given time and take a seat. A car consists out of 9 seats for 9 people (3x3 seats). After 3 seats are full, the safety bars of the 3 seats will close. After all the cars (we have 3 cars in total, so 3x9 places = 27 places) are full the coaster starts.

Differences between CountDownLatch and CyclicBarrier

CyclicBarrier

The CyclicBarrier can be used to close the safety bars for each 3 seats. In the CyclicBarrier the subthread will wait for all 3 seats to be filled, before it can continue and can close the safety bar from each tread individually. Since it is cyclic it can be reused for each 3 seats.

CountDownLatch

The CountDownLatch can be used to start the roller coaster after all seats are taken. A sort of main thread will wait for all seats to be taken.

Code example

package Concurrency;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchVsCyclicBarrier
{
    private final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    private final Integer numberOfSeats = 27;
    private final Integer numberOfSeatsInOneRow = 3;

    private final CountDownLatch latch = new CountDownLatch(numberOfSeats);
    private final CyclicBarrier barrier = new CyclicBarrier(numberOfSeatsInOneRow);

    public void run() throws Exception
    {
        for (int person = 1; person < 28; person++) {
            int finalPerson = person;
            es.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Waiting for person " + finalPerson + " to take a seat");
                    try { Thread.sleep(1500); } catch(InterruptedException ignored) {}
                    System.out.println("Waiting to close safety bar for person " + finalPerson);
                    try { barrier.await(); } catch(Exception ignored) {}
                    System.out.println("Closing the safety bar for person " + finalPerson);
                    latch.countDown();
                }
            });
            Thread.sleep(100);
        }

        latch.await(); // Wait for all 27 seats to be taken
        System.out.println("Start the rollercoaster");
        es.shutdown();
    }

    public static void main(String[] args) throws Exception
    {
        new CountDownLatchVsCyclicBarrier().run();
    }
}
Joanniejoao answered 30/3, 2023 at 6:37 Comment(0)
B
0

Here are my observations : -----> 1. Where to use what : In a Cyclic barrier threads have to wait for other threads to give some output, and then all threads have to resume processing. So after completing its execution, each thread calls await() method and waits. When the barrier detects that all the threads have reached it, it notifies all its waiting threads and they can resume further execution. Barrier keeps track of count.

In a CountDownLatch single main thread waits for all threads to complete. Each thread reduces the count by 1 after completing execution. After the count reaches 0, the main thread can resume further execution. Main thread keeps track of count.

Phaser : In both ways, count of threads should be known beforehand. It is not possible to add/remove threads dynamically. If the count is not reached, thread keeping track of count will wait infinitely. With the Phaser, the number of threads can be dynamic and vary with time. It is similar to Cyclic Barrier. Thread registers with a barrier. After completing execution, it has two options. It can signal that it has arrived at the barrier point and without waiting for others it can deregister from the Phaser. Second option is that it can wait for the other registered Threads to arrive at the barrier point.

  1. Counts : While creating a CyclicBarrier the no of worker threads includes main thread if it is also going to wait for other threads to complete. While creating a CountDownLatch just needs to mention how many worker threads main thread will to wait to complete. In CountDownLatch there is the concept of main and worker threads and the main waiting thread is not included in count while creating a latch. Phaser can return the current count of registered Threads.

  2. Intent of await() : In CyclicBarrier :: await() all threads including main thread are equal and wait for each other. Hence await() should be given in all threads(worker as well as main thread). CountDownLatch :: await() is given in main thread only and it makes main thread wait till other worker threads make count to 0. Thus internal implementation of both await() is different. There are two concepts in Phaser :: arrival to the barrier(arrive() and arriveAndDeregister()) and waiting(awaitAdvance(phase_number)) for other threads.

  3. Parties and Waiting threads : CountDownLatch cannot give number of waiting threads but can give parties(cl.getCount()), CyclicBarrier can give no of waiting threads cb.getNumberWaiting(), and parties(cb.getParties())

  4. Work responsibilities : Worker thread in countdownlatch need to do countdown(), and await() is done by one single main thread. In cyclicBarrier worker and main threads all do only await() on each other.

  5. Reuse : CyclicBarrier can be reused. cb.await() works for new threads say t1, t2 and main. And second call to cb.await() for new threads t3,t4 and main also works. Main will wait in both calls, that is system is automatically internally resetting the count(or reset()) after barrier is exitted. CountDownLatch cannot be reused. - cl.await() works for new threads say t1, t2 and main. Main thread waits for t1, t2 to complete. But for second cl.await() call for new threads t3,t4 and main will not wait. Phaser object can be re-used again once all the Threads in the set have crossed the barrier point.

  6. After Finish Events : While creating, no finish event can be given in CountDownLatch but it can be given in CyclicBarrier.

class MyClass {

static class MyThread implements Runnable
{

    long waitTime;
    CyclicBarrier cyclicBarrier;
    CountDownLatch countdownlatch;
    Phaser phaser;


    MyThread(  long waitTime, CyclicBarrier cyclicBarrier, CountDownLatch countdownlatch, Phaser phaser){
        this.waitTime = waitTime;
        this.cyclicBarrier = cyclicBarrier;
        this.countdownlatch = countdownlatch;
        this.phaser = phaser;
        this.phaser.register(); //Note additional step here
    }

    @Override
    public void run() {

            try {

                Thread.sleep(waitTime);

                // Diff 4 -----> countdownlatch worker threads need to do countdown and await is done by one single main thread
                //, cyclicBarrier worker threads await on each other
                countdownlatch.countDown(); 
                cyclicBarrier.await();
                phaser.arriveAndAwaitAdvance();

                System.out.println("cyclicBarrier :: " + 
                        ", name :: " + Thread.currentThread().getName() 
                        + ", parties :: " + cyclicBarrier.getParties() 
                        + ", waiting :: "+ cyclicBarrier.getNumberWaiting()); 

                System.out.println("countdownlatch :: " + 
                            "name :: " + Thread.currentThread().getName()  +
                         ", parties :: "+countdownlatch.getCount() +
                         ", waiting :: " + "No method!!" ); 
                System.out.println("phaser :: " + 
                        "name :: " + Thread.currentThread().getName()  +
                     ", parties :: "+phaser.getRegisteredParties() +
                     ", phase :: " + phaser.getPhase()); 

                phaser.arriveAndAwaitAdvance();
                System.out.println("phaser :: " + 
                        "name :: " + Thread.currentThread().getName()  +
                     ", parties :: "+phaser.getRegisteredParties() +
                     ", phase :: " + phaser.getPhase());

                phaser.arriveAndAwaitAdvance();
                System.out.println("phaser :: " + 
                        "name :: " + Thread.currentThread().getName()  +
                     ", parties :: "+phaser.getRegisteredParties() +
                     ", phase :: " + phaser.getPhase());
                phaser.arriveAndDeregister(); 
                if (phaser.isTerminated()) { 
                    System.out.println("Phaser is terminated"); 
                } 

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }

    }

}

public static class MyCBFinishEvent implements Runnable{

    public void run() {

           System.out.println("All threads have reached common barrier point "
                        + ", CyclicBarrrierFinishEvent has been triggered");
           System.out.println("You can update shared variables if any");
    }

}

public static void main(String [] args) throws InterruptedException, BrokenBarrierException{
    //Diff 1 ----- > No finish event can be given in CountDownLatch
    //Diff 5 ------> CyclicBarrier no of worker threads includes main thread, 
    //CountDownLatch is just how many threads, the main waiting thread is not included in count.
    CyclicBarrier cb = new CyclicBarrier(3, new MyCBFinishEvent());
    CountDownLatch cl = new CountDownLatch(2);
    Phaser ph = new Phaser();

    //Diff 2 ----> CountDownLatch cant give num of waiting threads, CyclicBarrier can getNumberWaiting threads
     System.out.println("Start CyclicBarrier - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("Start CountDownLatch - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

    Runnable t1 = new Thread(new MyThread( 10000, cb, cl, ph));
    Runnable t2 = new Thread(new MyThread( 5000, cb, cl,ph));
     Thread tt1 = new Thread(t1, "t1");
     Thread tt2 = new Thread(t2, "t2");
     tt1.start();
     tt2.start();

     //Diff 6 ---- > await meaning Main waits for t1 and t2 to complete, 
     //CyclicBarrier all are equal. each thread including main thread, if it wants to wait has to do await. 
     //CountDownLatch concept of waiting and workers. main thread await waits till other worker threads make count to 0.
     cb.await();
     cl.await();

     System.out.println("End CyclicBarrier call 1 - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
     System.out.println("End CountDownLatch call 1 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     System.out.println("main start created t3, t4 - parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

     Runnable t3 = new Thread(new MyThread( 6000, cb, cl,ph));
        Runnable t4 = new Thread(new MyThread( 100, cb, cl,ph));
         Thread tt3 = new Thread(t3, "t3");

         Thread tt4 = new Thread(t4, "t4");

         tt3.start();
         tt4.start();

        //Diff -3 -----> 
         //CyclicBarrier - can be reused, main thread waited for t3, t4 to complete.
         //CountDownLatch - for first cl.await(), main waited... second cl.await() call main did not wait!!! 
         cb.await();
         cl.await();


         System.out.println("End main - parties :: "+cb.getParties() + ", waiting :: " + cb.getNumberWaiting());
         System.out.println("end main parties :: "+cl.getCount() + ", waiting :: " + "No method!!" );

}

}

Bedplate answered 12/7, 2019 at 7:12 Comment(0)
W
0

CountDownLatch: "The Best Real Life Example is - Race"

(Any Type of Race for Example: Horse Race or Bike Race or Car Race etc.,)

The Horse Race is also one of the Best Real Life Example can implement using CountDownLatch.

  1. The Race Distance will be Announce or Fixed. (Race Distance in Km/Miles/Yards)
  2. Number of Horses will be participating in Race. (Horses Count)
  3. Before starting Race all horses will arrive at starting gate or starting point.
  4. Once all horses reached at starting gate/starting point then only Race will start.
  5. Once signaled - All horse will start at once / releases them all at once.
  6. All horses will start running... to finish Race Distance / to reach finishing point.
  7. Once all horses completed the Race Distance or Reaches finishing point.
  8. We get all horses position / places List - Winners List.
  9. Announce the Winner of the Race

We use Two CountDownLatch for Start and finish the Race.

CountDownLatch start  = new CountDownLatch(1); // Start signal - will be always 1 only once All Horses Reach at Starting Point signal for START RACE.

CountDownLatch finish = new CountDownLatch(horses_Count); // Number of horses participating in Race nothing but Threads/Horses Count.

Horses - is nothing but Threads.

start.await() : Each Horse/Thread once Reach at starting gate/starting point it will wait for other horses/Threads to reach at starting gate/starting point is nothing but - start.await();

start.countDown() : Once all horses/Threads reached at starting gate/starting point we signal to start Race is nothing but - start.countDown(); When start.countDown(); is called it will notifyAll() to All waiting Horses/Threads to Start Race.

finish.await() : Once all horses/Threads started Race the Main Thread will be wait to finish or complete by All horses/Threads is nothing but - finish.await();

finish.countDown(): Once each horse/Thread finish Race It will be reduce the count once last horse/Thread reduce count to ZERO then Race Completed/Finished finish.countDown(); When finish.countDown(); is called when count became to ZERO it will notify() to waiting Main Thread - All Horses/Threads Finished/Completed the RACE.

Warrenne answered 14/7, 2020 at 19:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.