What is a CyclicBarrier and what is its barrier action?
answer
- Reusable rendezvous of N parties
- All wait for all, then released together
- Barrier action runs once in the last arriver
- Cyclic: auto-resets each round
- BrokenBarrierException on failure
basics
~20 sA CyclicBarrier is a reusable meeting point for a fixed number of threads. Each thread calls await() and blocks until all of them arrive. Then they all proceed, and the barrier resets so it can be used again for the next round.
solid answer
~50 sCyclicBarrier lets a fixed set of N threads (parties) wait for each other at a common point. You create it with the number of parties and optionally a barrier action (a Runnable). Each thread calls await(); the call blocks until all N parties have arrived. When the last party arrives, the optional barrier action runs once in that last thread, then all parties are released together. Crucially it is cyclic: after release the barrier automatically resets to its initial state, so the same barrier can be reused for repeated phases — ideal for iterative parallel algorithms that proceed in lockstep rounds. await() returns each thread's arrival index. If any waiting thread is interrupted, times out, or the barrier is broken, all other waiters get a BrokenBarrierException so no one is left hung. The barrier action is the natural place to merge or hand off per-round results before the next round starts.
code
java · 15 linesint parties = 3;
CyclicBarrier barrier = new CyclicBarrier(parties,
() -> System.out.println("round complete, merging results"));
for (int i = 0; i < parties; i++) {
new Thread(() -> {
try {
for (int round = 0; round < 5; round++) {
computeRound(round);
barrier.await(); // wait for the others, then loop again
}
} catch (InterruptedException | BrokenBarrierException e) {
Thread.currentThread().interrupt();
}
}).start();
}go deeper
Knows N threads each call await() and all proceed together when the last arrives.
Explains reusability across rounds, the barrier action running once in the last arriver, and the arrival-index return value.
Reasons about breakage (interrupt/timeout/reset/action-throws → BrokenBarrierException), happens-before across rounds, and chooses barrier over latch for lockstep algorithms.
Designs phased parallel algorithms, compares CyclicBarrier with Phaser (dynamic parties) and fork/join, and handles failure recovery and observability of broken barriers.
## The problem it solves Some parallel algorithms run in **rounds**: every worker does part of round 1, then they must all **synchronise** before any starts round 2 (e.g. a grid simulation where each cell's next value depends on this round's neighbours). You need a **reusable rendezvous** where a fixed group of threads wait for each other repeatedly. That is `CyclicBarrier`. ## What it is `java.util.concurrent.CyclicBarrier` is a synchronizer that makes **N threads wait for each other** at a barrier point. - You construct it with the number of **parties**: `new CyclicBarrier(4)`. - Each participating thread calls **`await()`**, which **blocks** until **all N parties** have called `await()`. - When the **last** party arrives, all parties are released **together**, and the barrier **resets** to its initial state automatically — hence *cyclic*. ### Key terms - **Party**: one of the fixed number of threads the barrier expects. The count is the number of participants, *not* a countdown of events. - **Rendezvous**: a meeting point — everyone waits until everyone has arrived. - **Cyclic / reusable**: after a release the barrier is ready for another round with no manual reset. ## The barrier action You may pass an optional **`Runnable` barrier action**: `new CyclicBarrier(4, () -> mergeResults())`. When the last party arrives, **before** any party is released, this action runs **exactly once**, executed **in the thread of the last arriving party**. It is the perfect place to do per-round bookkeeping — merge partial results, advance a shared phase counter, decide whether to stop — knowing all parties have finished the round and none has started the next. If the barrier action throws, the barrier is broken and all parties get a `BrokenBarrierException`. ## await() return value and breakage - `await()` returns an **arrival index**: `getParties() - 1` for the first thread to arrive down to `0` for the last. Useful to assign one party a special task. - **Breaking**: if a waiting thread is **interrupted**, an `await(timeout)` **times out**, the **barrier action throws**, or someone calls **`reset()`**, the barrier becomes *broken*: every other waiting (and subsequently arriving) thread throws `BrokenBarrierException`. This prevents threads being stranded forever when one party fails. `reset()` returns a broken/used barrier to the initial state for a fresh start. - `getNumberWaiting()` and `isBroken()` expose state for diagnostics. ## Memory visibility Actions before a thread's `await()` *happen-before* the barrier action, which *happen-before* actions after `await()` returns in all parties. So each round's results are safely published to the next round. ## Contrast with CountDownLatch A latch counts **events** and is **one-shot**; any thread can count it down and the counted-down threads need not wait. A barrier counts **parties that wait on each other**, is **reusable**, and each party both arrives and waits. Use a barrier for lockstep phases; a latch for a single 'start' or 'all done' signal.
- In which thread does the barrier action run?In the thread of the last party to arrive, exactly once, after all have arrived and before any is released.
- What does await() return, and why is that useful?It returns the arrival index (parties-1 down to 0). You can use it to give one designated party, e.g. index 0, a special role in that round.
A group of hikers agreeing to regroup at each trail marker: nobody moves on until everyone has reached the marker. At each marker (the barrier action) the leader can do a headcount, then they all set off together — and they do this again at the next marker.
saying these in an interview costs you the question
- Saying the barrier action runs in a separate or every thread (it runs once, in the last arriver)
- Treating CyclicBarrier as one-shot like a latch
- Thinking the constructor count is a countdown of events rather than the number of participating threads
- Ignoring BrokenBarrierException and assuming a stuck party simply waits forever