Imagine a seminar which will start only when a certain number of attendees(say, 5) have arrived.
If asked, how would you achieve this in a java program.
The answer is by using a CyclicBarrier.

What is a CyclicBarrier

CyclicBarrier is a utility that is used to achieve thread synchronization in java.
When there are more than 1 threads, it allows the threads to wait for each other till all the threads reach a common point of execution.
This common point is called barrier point.
If there are 5 threads and 1 thread reaches the barrier point first, then it will wait till the other 4 also reach the same point.
Similarly, if 2 threads reach the barrier point, then they will wait till the other 3 also reach there.
Waiting threads can not move past the barrier point till all the threads reach there.

How CyclicBarrier Works

In order to use CyclicBarrier, create an object of java.util.concurrent.CyclicBarrier class. This class was added in java 1.5.
It takes an integer as argument which is the total number of threads that will wait for each other to reach the barrier point.
Example,

CyclicBarrier barrier = new CyclicBarrier(3);

CyclicBarrier class has an await() method. A thread when calls this method on an object of CyclicBarrier goes into waiting state till all the threads given at the time of creation of CyclicBarrier call await.
Thus, for the above CyclicBarrier, if a thread calls await(), then its execution will halt till two other threads also call await(). This way, all the threads will be at the same point.

Therefore, await() method can be considered as a barrier point in CyclicBarrier. When all the threads call await() method, then barrier is said to be broken or crossed.
Javadoc of await() method states

Waits until all parties have invoked await() on this barrier.

where parties means threads that are part of CyclicBarrier.
Following are some important points regarding await method

  1. All threads should call await on the same CyclicBarrier object.
  2. If even one thread does not call await, then all the threads that have called await will keep on waiting forever.
  3. If there are 5 threads in a CyclicBarrier out of which 4 have called await and are waiting for the 5th thread to call await.
    But 5th thread calls reset method in CyclicBarrier object, then all the threads will terminate by throwing a java.util.concurrent.BrokenBarrierException.
  4. There is an overloaded await method which takes an integer as a timeout. If a thread calls await, then it waits for the specified time for other threads to cross the barrier or call await() method else terminates with a java.util.concurrent.TimeoutException.

CyclicBarrier example

Below is a class that represents a task performed by a thread.
It implements java.lang.Runnable interface and overrides its run() method.

Learn how to override a method in java here.

Object of this class is supplied to different threads.

Worker.java

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

class Worker implements Runnable { 
  CyclicBarrier barrier; 
  /** * Constructor 
  * @param b 
  */ 
  public Worker(CyclicBarrier b) { 
    this.barrier = b; 
  } 

  @Override 
  public void run() { 
    try { 
      System.out.println("Started: " + Thread.currentThread().getName());
      // wait till all the threads reach this point 
      barrier.await(); 
    } catch (InterruptedException e) { 
       e.printStackTrace(); 
    } catch (BrokenBarrierException e) {
       e.printStackTrace(); 
    }
  }
} 
System.out.println("Finished: " + Thread.currentThread().getName()); 
} 
}

Note that the object of Worker has a CyclicBarrier. Since the same Worker object is supplied to the threads, all threads will have access to same CyclicBarrier object.

Below is the class which creates a CyclicBarrier object with a count of 4.
This means that we are synchronizing 4 threads and if a thread calls await on this CyclicBarrier object, then it will be stuck till other 3 threads also call await() on the same CyclicBarrier object.
It then creates an object of Worker class supplying it the CyclicBarrier object and creates 3 threads with the Worker object. Finally it starts the three threads and itself calls await().

Learn how to create and start a thread here.

Now till all the other 3 threads call await(), this thread will be stuck. As soon as the threads start, they call await() and when all the four threads have called await(), they continue execution past the call to await().

CyclicBarrierDemo.java

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

public class CyclicBarrierDemo { 
  public static void main(String[] args){ 
    // create an object of cyclicbarrier with a thread count of 4 
    CyclicBarrier barrier = new CyclicBarrier(4); 
    // create a task 
    Task obj = new Task(barrier); 
    // create three worker threads 
    Thread t1 = new Thread(obj); 
    Thread t2 = new Thread(obj); 
    Thread t3 = new Thread(obj); 
    // start threads 
    t1.start(); 
    t2.start(); 
    t3.start(); 
    try { 
      System.out.println("Main: Waiting for the threads to call await"); 
      // 4th thread to call await 
      barrier.await(); 
      Thread.sleep(2000); 
    } catch (BrokenBarrierException e) { 
      e.printStackTrace(); 
    } catch (InterruptedException e) { 
      e.printStackTrace(); 
    }
    System.out.println("All Threads completed!!!"); 
  } 
}

Below output will clarify the flow of program

Main: Waiting for the threads to call await
Started: Thread-2
Started: Thread-1
Started: Thread-0
Finished: Thread-0
Finished: Thread-2
Finished: Thread-1
All Threads completed!!!

Order of thread execution might be different every time the program is executed.

CyclicBarrier: Version 2

java.util.concurrent.CyclicBarrier has another constructor which takes a thread count and an object of java.lang.Runnable as argument.
This second argument is the task which is executed when all the threads have crossed the barrier or have called await() method.
This task will be executed by the last thread that crosses the barrier or calls await().
This task is an object of type java.lang.Runnable and is also called Barrier Action.
Thus, a CyclicBarrier can be used to perform a task when all threads have reached a common point or you can also say, it can be used to combine the result of all the threads after their execution.
Example,
Below code creates an object of CyclicBarrier along with a task that will be executed when all the threads cross the barrier.
Rest of the program remains the same as written above.

// barrier with finish task 
CyclicBarrier barrier = new CyclicBarrier(4, 
                   new Thread(new Runnable() { 
                     @Override 
                     public void run() { 
                       System.out.println(Thread.currentThread().getName() + 
                             " has crossed the barrier last"); 
                     } 
                   }
                 ));

Output of this code put in the above program is

Waiting for the threads to call await
Started: Thread-3
Started: Thread-2
Started: Thread-1
Thread-3 has crossed the barrier last
Finished: Thread-3
Finished: Thread-1
Finished: Thread-2
All Threads completed!!!

Remember that the last thread will be different every time the program is executed.

BrokenBarrierException

A java.util.concurrent.BrokenBarrierException is raised in the following cases

  1. If some threads are waiting after calling await() method and another thread calls reset() method on the same CyclicBarrier object, all the waiting threads terminate by throwing this exception.
  2. A thread has already called reset() method and another thread calls await(), this exception will be raised.
  3. A thread has terminated with a TimeoutException after calling await() with a timeout, other threads which call await() afterwards raise this exception.

Remember that the CyclicBarrier object should be the same in all the cases.

Where to use CyclicBarrier

  1. A CyclicBarrier can be used to break a large task into smaller sub-tasks where each task will be performed by a separate thread and the result of all the threads can be combined in the final task of CyclicBarrier or the Barrier Action.
    Example, Summing up the rows of a matrix where each thread will sum up a single row and final sum will be calculated in Barrier Action.
  2. Implementation of a multi player game where the game will start only when all the players have reached.

Hope this article helped you to understand the concept of CyclicBarrier in java.

Leave a Reply