Definition
- CountDownLatch(N) – a one-time gate; any thread calls
countDown()to decrement, any thread callsawait()to block until count reaches zero; cannot be reset. - CyclicBarrier(N) – a reusable sync point; the same N threads call
await(), all blocked until the Nth arrives, then all proceed simultaneously; auto-resets after each trip. - Counting vs waiting – in a latch, counting and waiting threads can be different; in a barrier, the same threads do both.
- Barrier action – CyclicBarrier accepts an optional Runnable that executes when all threads arrive.
- Broken state – if a barrier thread is interrupted or times out, all other waiting threads get
BrokenBarrierException.
At National Bank of India: CountDownLatch(3) is the branch manager waiting for 3 department reports. Accounting submits and counts down. Loans submits and counts down. Compliance submits and counts down. Manager proceeds when count reaches zero. Cannot reuse: need a new latch tomorrow. CyclicBarrier(3) is 3 audit teams reaching checkpoint-1 together, then all proceeding to checkpoint-2, then reaching it together again. Same teams, multiple checkpoints, barrier auto-resets.
Understanding the Concepts
How does CountDownLatch work?
CountDownLatch(N) starts with a count of N. Any thread can call countDown() to decrement. Threads calling await() block until the count reaches zero.
package com.bank.service;
import java.util.concurrent.*;
public class LatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
ExecutorService pool = Executors.newFixedThreadPool(3);
pool.submit(() -> { generateReport("Accounting"); latch.countDown(); });
pool.submit(() -> { generateReport("Loans"); latch.countDown(); });
pool.submit(() -> { generateReport("Compliance"); latch.countDown(); });
latch.await(); // blocks until count = 0
System.out.println("All reports ready. Merging.");
// latch.await() again → returns immediately (count stays at 0)
pool.shutdown();
}
static void generateReport(String dept) {
System.out.println(dept + " report done");
}
}
Accounting report done
Loans report done
Compliance report done
All reports ready. Merging.
How does CyclicBarrier work?
CyclicBarrier(N) blocks each of N threads until all N have called await(). When the Nth arrives, all are released. The barrier auto-resets for the next trip.
package com.bank.service;
import java.util.concurrent.*;
public class BarrierDemo {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () ->
System.out.println("--- All reached checkpoint ---"));
ExecutorService pool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 3; i++) {
final int id = i;
pool.submit(() -> {
try {
System.out.println("Auditor-" + id + " phase-1");
barrier.await();
System.out.println("Auditor-" + id + " phase-2");
barrier.await(); // reusable!
} catch (Exception e) {
Thread.currentThread().interrupt();
}
});
}
pool.shutdown();
}
}
Auditor-0 phase-1
Auditor-1 phase-1
Auditor-2 phase-1
--- All reached checkpoint ---
Auditor-0 phase-2
Auditor-1 phase-2
Auditor-2 phase-2
--- All reached checkpoint ---
How do they compare?
| Feature | CountDownLatch | CyclicBarrier |
|---|---|---|
| Reusable | No (one-time) | Yes (auto-resets) |
| Who counts/waits | Different threads OK | Same threads |
| Reset | Cannot reset | Automatic per trip |
| Barrier action | None | Optional Runnable |
| Exception | N/A | BrokenBarrierException |
| Use case | Wait for N events | N threads sync at point |
| Thread count | Waiters != counters | Waiters = counters = N |
What is BrokenBarrierException?
If a thread waiting at the barrier is interrupted or times out, all other waiting threads receive BrokenBarrierException. The barrier is in a broken state and must be reset with barrier.reset() before reuse.
What about Semaphore?
Semaphore limits concurrent access to a resource by issuing a fixed number of permits.
Semaphore dbSemaphore = new Semaphore(5); // max 5 concurrent DB calls
try {
dbSemaphore.acquire();
queryDatabase();
} finally {
dbSemaphore.release();
}
What about Phaser?
Phaser is a flexible synchronizer that supports dynamic registration and multiple phases. It combines features of both CountDownLatch and CyclicBarrier.
When should you use each?
- CountDownLatch: service startup (wait for N components to initialize), test setup (wait for server to be ready), batch completion (wait for N tasks).
- CyclicBarrier: multi-phase simulation, parallel batch processing with phase boundaries, synchronized testing.
- Semaphore: connection pooling, rate limiting, resource throttling.
What are common mistakes?
// WRONG: reusing a triggered CountDownLatch
latch.await(); // count = 0
// ... next day ...
latch.await(); // returns immediately! Need a new latch.
// WRONG: wrong party count in CyclicBarrier
CyclicBarrier barrier = new CyclicBarrier(4); // expects 4 threads
// Only 3 threads call await() → deadlock! 4th never arrives.
What are common interview follow-up questions?
- Can CountDownLatch count up? No, only down. Use Phaser for dynamic registration.
- What happens if you call countDown() more than N times? Nothing: count stays at zero.
- Can CyclicBarrier be used with fewer threads than the party count? No, it will deadlock waiting for the Nth thread.
Visual Overview
CountDownLatch(3) CyclicBarrier(3)
Thread-A: countDown() 3→2 Thread-A: await() ──┐
Thread-B: countDown() 2→1 Thread-B: await() ──┤ all blocked
Thread-C: countDown() 1→0 Thread-C: await() ──┘ 3rd arrives!
│ │
▼ ▼
Main: await() unblocks All 3 released simultaneously
(count = 0, one-time) (barrier resets for next trip)
Latch: different counters/waiters
Barrier: same threads count and wait
Key Takeaway
CountDownLatch and CyclicBarrier are both synchronizers, but they solve different problems. CountDownLatch(N) is a one-time gate: N events count down, waiters unblock when the count reaches zero, and it cannot be reset. The counting threads and waiting threads can be different. Use it for "wait for N things to happen."
CyclicBarrier(N) is a reusable sync point: N threads all call await(), all are blocked until the Nth arrives, then all proceed simultaneously. It auto-resets after each trip for multiple phases. The same threads that wait are the ones being counted. Use it for "N threads synchronize at checkpoints between phases."
At National Bank of India, the EOD batch uses CyclicBarrier(10) for 10 threads processing three phases: interest calculation, statement generation, and notification sending. All threads must complete each phase before any can start the next. CountDownLatch(4) coordinates the final archive step, waiting for four department batches to complete.
Remember one sentence: latch counts down events one-time, barrier synchronizes the same threads at reusable checkpoints.
---