Lesson 41.2 · Concurrency-Aware Data Structures
Coordinating Threads: Latches, Semaphores, Conditions
CountDownLatch waits for events, Semaphore limits how many threads proceed, wait/notifyAll and Condition objects let threads sleep until a state changes. BlockingQueue packages the producer-consumer pattern.
14 min
Think of it like this
A relay race: the second runner waits until the baton (a latch) arrives. A car park with 50 spaces lets cars in while the counter (a semaphore) is above zero. A waiter who sleeps until the kitchen rings the bell is using a condition.
1.Which tool
CountDownLatch(n): await() blocks until countDown() has been called n times ("wait until X happened"). Semaphore(k): acquire() takes one of k permits, release() returns it ("at most k at once", or ping-pong between threads with permits of 0 and 1).
wait / notifyAll inside synchronized, or Lock + Condition (await/signal): always wait in a while loop that re-checks the condition, because wake-ups can be spurious and another thread may have changed the state first.
BlockingQueue (ArrayBlockingQueue, LinkedBlockingQueue): put blocks when full, take blocks when empty. It's the producer-consumer pattern done for you, and the backbone of thread pools.
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class Main {
public static void main(String[] args) throws Exception {
BlockingQueue<Integer> q = new ArrayBlockingQueue<>(2); // holds at most 2 items
Thread producer = new Thread(() -> {
try {
for (int i = 1; i <= 5; i++) q.put(i); // blocks while the queue is full
q.put(-1); // "no more items" marker
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
producer.start();
int sum = 0;
for (int x = q.take(); x != -1; x = q.take()) sum += x; // blocks while empty
producer.join();
System.out.println("consumed sum = " + sum);
}
}Output
consumed sum = 15Remember
- Latch: wait for events. Semaphore: limit concurrency.
- Always wait in a while loop.
- Prefer BlockingQueue over hand-written wait/notify.
Common mistakes
- Using if instead of while around wait().
- notify() instead of notifyAll() when several kinds of waiters share a monitor.