6.5 Synchronizers & Coordination Utilities: CountDownLatch, CyclicBarrier & Semaphore
← Back to Chapter 6: Multithreading & Concurrency
Java's java.util.concurrent package provides specialized synchronization primitives to orchestrate complex multi-threaded workflows.
1. CountDownLatch: One-Time Countdown Gate
Blocks one or more threads until a set of operations completed by other threads decrements the count down to zero:
int workerCount = 3;
CountDownLatch latch = new CountDownLatch(workerCount);
for (int i = 0; i < workerCount; i++) {
new Thread(() -> {
try {
// Perform init work...
} finally {
latch.countDown(); // Decrement latch counter
}
}).start();
}
latch.await(); // Main thread blocks until counter reaches 0
System.out.println("All services initialized. System operational!");
- Key Characteristic: Non-reusable. Once the count reaches zero, the latch cannot be reset.
2. CyclicBarrier: Multi-Thread Meeting Point
Blocks a fixed group of threads until all threads arrive at the barrier:
CyclicBarrier barrier = new CyclicBarrier(3, () -> {
System.out.println("All 3 threads arrived! Processing combined batch...");
});
// Inside worker threads:
barrier.await(); // Waits for all peers, then automatically resets for the next round!
- Difference from CountDownLatch: Reusable (
Cyclic). Threads wait for each other repeatedly in iterations.
3. Semaphore: Resource Rate Limiting & Permits
Maintains a set of permits to throttle concurrency (e.g. limiting simultaneous database connections):
Semaphore connectionPool = new Semaphore(10); // Max 10 simultaneous threads
connectionPool.acquire(); // Blocks if 0 permits available
try {
// Access restricted database connection
} finally {
connectionPool.release(); // Return permit
}
4. BlockingQueue: Producer-Consumer Engine
- Thread-safe queues where
put()blocks if the queue is full, andtake()blocks if the queue is empty. - Implementations:
ArrayBlockingQueue(bounded array),LinkedBlockingQueue(optionally bounded nodes),PriorityBlockingQueue(heap sorted).