What are the key differences between CountDownLatch and CyclicBarrier, and when would you choose each?
answer
- Latch = one-shot events; barrier = reusable parties
- Latch decouples signaller/waiter; barrier = mutual rendezvous
- Only barrier has a barrier action
- Barrier breaks (BrokenBarrierException); latch has no broken state
- Repeated rounds → barrier (or Phaser for dynamic counts)
basics
~20 sA CountDownLatch is one-shot: any thread counts it down and waiters proceed at zero. A CyclicBarrier is reusable: a fixed set of threads wait for each other, then all go together and it resets. Use a latch for a single start/done signal, a barrier for repeated lockstep rounds.
solid answer
~50 sThey look similar but differ on several axes. CountDownLatch is single-use; once the count reaches zero it stays open and cannot reset. CyclicBarrier is reusable; it resets automatically after every release. With a latch the count is a number of events and any thread can countDown(), and the threads that count down need not be the ones that await; with a barrier the count is the number of participating parties, and each party both arrives and waits. A latch decouples signallers from waiters (1 waiter, N signallers, or vice versa); a barrier is a mutual rendezvous (N threads waiting on each other). Only the barrier has a barrier action that runs once when the last party arrives. On failure, a barrier breaks cleanly with BrokenBarrierException; a latch has no such notion. Choose a latch for a one-time 'go' or 'all done' signal; choose a barrier for iterative algorithms that synchronise every round.
go deeper
Knows latch is for waiting on completion/start once, barrier is for threads waiting on each other repeatedly.
Lists reusability, count meaning (events vs parties), and the barrier action as the main differences and picks the right one for a scenario.
Articulates the full comparison including failure semantics (BrokenBarrierException) and happens-before, and justifies the choice for a given algorithm.
Generalises to Phaser/CompletableFuture, weighs maintainability and failure recovery, and sets coordination patterns and guidance for a team.
## Why compare them Both `CountDownLatch` and `CyclicBarrier` live in `java.util.concurrent` and both make threads **wait**, so they are easily confused. The differences are about *who waits for whom*, *reusability*, and *failure handling*. ## Side-by-side | Aspect | CountDownLatch | CyclicBarrier | |---|---|---| | Reusability | **One-shot** — opens at zero, never resets | **Reusable** — auto-resets after each release | | What the count means | Number of **events** to wait for | Number of **parties** (threads) that meet | | Who advances it | **Any** thread via `countDown()` | Each **party** by calling `await()` | | Waiter vs signaller | Decoupled (waiters and counters are independent sets) | Same set: each party both arrives **and** waits | | Action on completion | None | Optional **barrier action**, run once by the last arriver | | Failure semantics | No 'broken' state | **`BrokenBarrierException`** on interrupt/timeout/reset/action-throw | | Typical shape | 1 waiter ↔ N signallers (or N waiters ↔ 1) | N ↔ N mutual rendezvous | ### Term definitions - **One-shot**: the synchronizer can be used exactly once; after it opens it is permanently open. - **Party**: one of the fixed N threads a barrier expects, each of which both arrives and waits. - **Rendezvous**: a meeting point where everyone waits until everyone arrives. - **Barrier action**: a `Runnable` the barrier runs once, in the last-arriving thread, before releasing the group. - **Broken barrier**: a state a barrier enters when a participant fails (interrupt/timeout/reset/action throws); all other waiters then throw `BrokenBarrierException` instead of hanging. ## Choosing between them **Use `CountDownLatch` when:** - A coordinator must wait until **N independent events** complete once (e.g. wait for N services to report ready at startup). Workers `countDown()`; coordinator `await()`. - You want a **single start gate**: many threads `await()` a latch of count 1; the controller `countDown()` to release them all simultaneously, once. - The signallers and waiters are **different** sets of threads. **Use `CyclicBarrier` when:** - A fixed group runs in **repeated synchronized rounds** (iterative simulations, matrix steps, multi-phase tests) and must regroup each round. - You want a **per-round hook** (the barrier action) to merge results or advance a phase between rounds. - The participants are a **fixed, mutually-waiting** set. ## A subtle gotcha A latch tolerates fewer or more `countDown()` calls than expected gracefully (extra calls are no-ops; too few means it never opens). A barrier requires **exactly** the configured number of parties to arrive each round; if one party dies without arriving, the others wait until interrupted/timed out and then break. For dynamically changing party counts, reach for **`Phaser`** instead, which generalises the barrier with registration/deregistration. ## Memory visibility (both) Both give *happens-before*: a latch publishes a signaller's pre-`countDown()` writes to a post-`await()` reader; a barrier publishes each party's pre-`await()` writes to all parties after the barrier (through the barrier action). So shared results computed before the sync point are safely visible after it.
- You need a synchronization point where the number of participating threads changes between rounds. Which class fits?Phaser — it generalises CyclicBarrier with dynamic register()/arriveAndDeregister(), which neither latch nor barrier supports.
- Can you emulate a one-shot start gate with a CyclicBarrier?Loosely yes (one round of N parties), but a CountDownLatch of count 1 is simpler and clearer for a pure start/done signal, and it does not require the waiters to also be the parties.
saying these in an interview costs you the question
- Saying both are reusable, or both are one-shot
- Claiming the latch count and barrier count mean the same thing (events vs parties)
- Thinking only the waiting threads can countDown() a latch
- Forgetting the barrier action exists only on CyclicBarrier
- Not knowing a barrier can break, leaving the impression a failed party hangs the rest forever