Skip to main content
  1. Java Concurrency (java.util.concurrent)/

CyclicBarrier

2 mins

CyclicBarrier is a synchronizer that allows a fixed number of threads to wait for each other at a common point. Unlike CountDownLatch, it can be reset and reused.

Source Code #

View Source on GitHub

Implementation Mechanism #

Interestingly, CyclicBarrier is not built directly on AQS. Instead, it uses a ReentrantLock and a Condition to coordinate threads. When a thread calls await(), it acquires the lock, decrements the count, and waits on the Condition if the count is not zero. When the last thread arrives, it signals all other threads to proceed and resets the count for the next cycle.

private final ReentrantLock lock = new ReentrantLock();
private final Condition trip = lock.newCondition();
private int count; // Initially set to parties

public int await() {
    final ReentrantLock lock = this.lock;
    lock.lock();
    try {
        int index = --count;
        if (index == 0) {
            // Run barrier action if provided
            final Runnable command = barrierCommand;
            if (command != null) command.run();
            
            // Signal all waiting threads and start new generation
            nextGeneration();
            return 0;
        }
        
        // Wait until signaled or interrupted
        for (;;) {
            trip.await();
            // ... check for generation changes ...
        }
    } finally {
        lock.unlock();
    }
}

Canonical Usage #

When to use: Use CyclicBarrier when you have a fixed-size group of threads that must repeatedly perform a computation in phases (e.g., a multi-phase data simulation where everyone must finish phase 1 before anyone starts phase 2).

Common Patterns:

  • Iterative Parallel Computation: Dividing a large problem into parts, where each thread computes its part, waits for the others, and then everyone proceeds to the next iteration.
  • Barrier Actions: Providing a custom Runnable that runs exactly once when the barrier is tripped, which is useful for aggregating results between phases.
// Barrier for 4 threads with a barrier action to summarize results
CyclicBarrier barrier = new CyclicBarrier(4, () -> {
    System.out.println("Phase complete. Summarizing partial results...");
    summarize();
});

// In each of the 4 worker threads
public void run() {
    try {
        doWorkPhase1();
        barrier.await(); // Wait for the other 3 threads

        doWorkPhase2();
        barrier.await(); // Wait for the other 3 threads again
    } catch (InterruptedException | BrokenBarrierException e) {
        return;
    }
}

Resilience: BrokenBarrierException #

Unlike CountDownLatch, CyclicBarrier is designed for failure-fast coordination. If any thread is interrupted or times out while waiting at the barrier, the barrier is considered “broken,” and all other waiting threads will receive a BrokenBarrierException to prevent deadlock.