Search code examples
javamultithreadingbarrier

Java thread has "join()" to wait all threads, then what use case do we need CyclicBarrier?


JDK doc says:

public class CyclicBarrier
extends Object

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
A CyclicBarrier supports an optional Runnable command that is run once per barrier point, after the last thread in the party arrives, but before any threads are released. This barrier action is useful for updating shared-state before any of the parties continue.

Then it gives a sample code, it works.

class Worker implements Runnable {
     int myRow;
     Worker(int row) { myRow = row; }
     public void run() {
       while (!done()) {
         processRow(myRow);

         try {
           barrier.await();
         } catch (InterruptedException ex) {
...
class Solver
...
     List<Thread> threads = new ArrayList<Thread>(N);
     for (int i = 0; i < N; i++) {
       Thread thread = new Thread(new Worker(i));
       threads.add(thread);
       thread.start();
     }

     // wait until done
     for (Thread thread : threads)
       thread.join(); // here we still need to wait all threads using join()
...

But still CyclicBarrier here seems redundant to me: threads "wait for each other", which is done by the for loop that calls thread.join()

In any case, as long as I wish to collect all results from threads, I'll have to wait for them to finish, right? If Thread.join() works, then why, or in what scenario do we need to introduce CyclicBarrier(ocam's razor?)


Solution

  • From Javadoc for Thread, calling join():

    Waits for this thread to die.

    If you have some threads that do nothing more interesting than "start" and "finish", you could perhaps use join() to wait for all of them to finish.

    From Javadoc for CyclicBarrier:

    CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other.

    There are a number of scenarios where you will want to define more interesting or dependent interactions between the threads themselves, scenarios where "wait for thread to die" does not provide adequate control.

    There are a number of other useful things in the java.util.concurrent package, such as Phaser and CountDownLatch. So, you may not have a need for any of these (yet), but they can be quite useful.