Java › Concurrency & Threads
How would you use CountDownLatch, CyclicBarrier, and Semaphore for different thread coordination scenarios, and what distinguishes their use cases?
AdvancedAnswer
CountDownLatch lets one or more threads wait until a set of operations being performed by other threads completes (a one-time, non-reusable count-down gate -- once it reaches zero, it stays open forever, useful for "wait until N things are done before proceeding"); CyclicBarrier makes a fixed number of threads wait for each other to all reach a common barrier point before any of them proceed (and, unlike CountDownLatch, is reusable/cyclic for repeated rounds of coordination, useful for phased parallel algorithms); Semaphore controls access to a limited number of permits, letting a bounded number of threads access a resource concurrently (like limiting concurrent connections to an external service), distinct from a simple lock which only ever allows exactly one thread through.
// CountDownLatch: wait for N worker threads to finish initialization before starting
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> { initialize(); latch.countDown(); }).start();
}
latch.await(); // blocks main thread until all 3 have counted down
// Semaphore: limit concurrent access to at most 5 threads at a time
Semaphore semaphore = new Semaphore(5);
semaphore.acquire();
try { callLimitedResource(); } finally { semaphore.release(); }Real-world example A service startup sequence uses CountDownLatch to block the main thread until all required subsystems (database connection pool, cache warm-up, config loading) have each independently signaled readiness on separate threads, while a separate rate-limiting layer uses a Semaphore to cap concurrent outbound calls to a fragile downstream API at exactly 10 at any given time.