Phaser and CyclicBarrier

In Java, Phaser and CyclicBarrier are both synchronization constructs provided by the java.util.concurrent package. They serve similar purposes in allowing threads to synchronize at certain points in their execution, but they have different characteristics and use cases.

Phaser

    • Phaser is a more flexible synchronization barrier than CyclicBarrier. It allows synchronization of threads in phases, where each phase can have a variable number of parties (threads).
    • It’s useful when the number of threads participating in synchronization can vary dynamically during runtime.
Important Constructors of Phaser:
Constructor Description
Phaser() Creates a phaser with no initially registered parties.
Phaser(int parties) Creates a phaser and registers the given number of parties.
Phaser(Phaser parent) Creates a phaser with no parties and sets a parent for hierarchical use.
Phaser(Phaser parent, int parties) Creates a phaser with the given parties and parent.

Important Methods of Phaser:
Method Signature Description
int register() Registers a new party and returns the current phase number.
int arrive() Signals arrival at the phaser without waiting for others.
int arriveAndAwaitAdvance() Arrives and waits for other parties to arrive. Blocks until phase advances.
int arriveAndDeregister() Arrives and then deregisters from the phaser.
int awaitAdvance(int phase) Waits for the phase to advance beyond the given value.
int getPhase() Returns the current phase number.
int getRegisteredParties() Returns the number of registered parties.
int getArrivedParties() Returns the number of arrived parties in the current phase.
int getUnarrivedParties() Returns the number of parties yet to arrive.
boolean isTerminated() Returns true if the phaser has terminated.
void forceTermination() Forces termination of the phaser.
boolean onAdvance(int phase, int parties) Hook method that can be overridden to control phase advancement behavior.

Program
//PhaserDemo.java
import java.util.concurrent.Phaser;
public class PhaserDemo {
    static class Worker implements Runnable {
        private final Phaser phaser;
        Worker(Phaser phaser) {
            this.phaser = phaser;
        }
        @Override
        public void run() {
            // Do some work
            System.out.println(Thread.currentThread().getName() + " is working");
            phaser.arriveAndAwaitAdvance(); // Wait for all threads to arrive
        }
    }
	public static void main(String[] args) {
        Phaser phaser = new Phaser(1); // 1 for main thread
        // Create threads
        Thread[] threads = new Thread[3];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Worker(phaser));
            phaser.register();
            threads[i].start();
        }
        // Main thread coordinating
        phaser.arriveAndAwaitAdvance(); // Wait for all threads to arrive
        // Do some work after all threads arrive
        phaser.arriveAndDeregister(); // Deregister main thread
    }
}

/*

C:\>javac PhaserDemo.java

C:\>java PhaserDemo
Thread-1 is working
Thread-2 is working
Thread-0 is working

C:\>java PhaserDemo
Thread-0 is working
Thread-2 is working
Thread-1 is working

C:\>java PhaserDemo
Thread-2 is working
Thread-0 is working
Thread-1 is working

*/

CyclicBarrier:

    • CyclicBarrier is used for synchronization among a fixed number of threads, where each thread waits at a barrier until all threads have reached it.
    • It’s useful when a fixed number of threads need to perform a task together or wait for each other to reach a common point.
Constructors of CyclicBarrier
Constructor Description
CyclicBarrier(int parties) Creates a barrier for the given number of threads (parties) to wait.
CyclicBarrier(int parties, Runnable barrierAction) Same as above, but executes the provided Runnable task once all threads reach the barrier.

Important Methods
Method Return Type Description
await() int Waits until all parties have invoked await() on this barrier. Returns arrival index.
await(long timeout, TimeUnit unit) int Waits with timeout; throws TimeoutException if timeout elapses.
getParties() int Returns the number of threads required to trip the barrier.
getNumberWaiting() int Returns the number of threads currently waiting at the barrier.
isBroken() boolean Returns true if the barrier is broken due to failure/interruption.
reset() void Resets the barrier to its initial state. If any parties are waiting, they will get a BrokenBarrierException.
Program

This program demonstrates the use of CyclicBarrier from the java.util.concurrent package to coordinate multiple threads. The goal is to make multiple threads wait for each other at a common barrier point, and only proceed when all have reached that point.

//CyclicBarrierDemo.java
import java.util.concurrent.CyclicBarrier;
class CyclicBarrierDemo {
    static class Worker implements Runnable {
        private final CyclicBarrier barrier;
        Worker(CyclicBarrier barrier) {
            this.barrier = barrier;
        }
        @Override
        public void run() {
            try {
                // Do some work
                System.out.println(Thread.currentThread().getName() + " is working");
                barrier.await(); // Wait for all threads to arrive
                // Barrier action after all threads reach the barrier
                System.out.println("Barrier action performed by " + Thread.currentThread().getName());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
	public static void main(String[] args) {
        CyclicBarrier barrier = new CyclicBarrier(3); // 3 threads needed
        // Create threads
        Thread[] threads = new Thread[3];
        for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(new Worker(barrier));
            threads[i].start();
        }
    }
    
}

/*
C:\>javac CyclicBarrierDemo.java

C:\>java CyclicBarrierDemo
Thread-2 is working
Thread-1 is working
Thread-0 is working
Barrier action performed by Thread-2
Barrier action performed by Thread-1
Barrier action performed by Thread-0

C:\>java CyclicBarrierDemo
Thread-0 is working
Thread-2 is working
Thread-1 is working
Barrier action performed by Thread-2
Barrier action performed by Thread-1
Barrier action performed by Thread-0

C:\>java CyclicBarrierDemo
Thread-1 is working
Thread-2 is working
Thread-0 is working
Barrier action performed by Thread-1
Barrier action performed by Thread-2
Barrier action performed by Thread-0

*/
Feature CyclicBarrier Phaser
Package java.util.concurrent java.util.concurrent
Introduction Java 5 Java 7
Participants Known Upfront? Yes, number of threads must be known when creating the barrier No, threads (parties) can register dynamically at runtime
Phases/Stages Supported Only supports one barrier point (can be reused, but it’s cyclic, not phased) Supports multiple phases; can advance to next phase after all threads reach a point
Reusability Reusable, but each reuse represents a new cycle of the same barrier Reusable and supports multiple phases easily
Dynamic Registration Not supported Supported (register() and bulkRegister()) methods
Thread Deregistration Not supported Supported via arriveAndDeregister()
Barrier Action Can be specified via a Runnable at construction Does not have a built-in action; you must handle it after phase advancement
Complexity Simpler to use for fixed thread scenarios More flexible and powerful for dynamic and multi-phase thread coordination
Use Case When a fixed number of threads must meet at a single barrier repeatedly When you need multiple synchronization phases or dynamic thread registration
Choosing Between Phaser and CyclicBarrier:
  • Use Phaser when you have a varying number of threads or when you need multiple synchronization points (phases).
  • Use CyclicBarrier when you have a fixed number of threads that need to synchronize at a single barrier point.

CyclicBarrier is best suited for fixed-size thread synchronization at a common barrier point, making it ideal for simple, one-time coordination. Phaser is more flexible, supporting dynamic registration and multi-phase synchronization, making it suitable for complex workflows involving changing numbers of threads.

Scroll to Top