Coordinating producers and consumers
A blocking queue is the backbone of the producer consumer pattern. Producers add items and consumers remove them, but the queue does more than store data: it parks threads that cannot proceed so they consume no CPU while waiting.
The two blocking conditions
- A consumer calling take on an empty queue blocks until an item arrives
- A producer calling put on a full bounded queue blocks until space frees up
- When the state changes, the queue signals the waiting threads so exactly the right ones wake
This turns the queue into a flow control valve. A fast producer is naturally throttled by a slow consumer because put stalls when the buffer fills.
Implementation shape
A common implementation uses one lock plus two condition variables, often called notFull and notEmpty. A put waits on notFull and signals notEmpty, while a take waits on notEmpty and signals notFull. Threads always recheck the condition in a loop after waking to guard against spurious wakeups.
Key idea
A blocking queue parks producers when full and consumers when empty, using condition variables to wake the right threads and provide built in flow control.