Condition Variables and Wait Notify
A condition variable lets a thread wait efficiently for some predicate to become true without busy waiting. It is always paired with a lock that protects the shared state the predicate reads.
The classic operations are wait and notify. A thread that finds the condition false calls wait, which atomically releases the lock and puts the thread to sleep. When another thread changes the state it calls notify to wake one waiter, or notify all to wake every waiter. The awoken thread reacquires the lock before returning from wait.
The golden rule is to always wait inside a loop that rechecks the predicate:
- The state may have changed again between the signal and your wakeup
- Several waiters may be woken but only one can proceed
- Spurious wakeups can return from wait with nothing actually changed
A canonical use is a bounded buffer. A consumer waits while the buffer is empty. A producer adds an item and notifies. A producer waits while the buffer is full, and a consumer removes an item and notifies. Each side sleeps cheaply until the other makes progress.
Forgetting to hold the lock while signaling, or notifying the wrong condition, leads to lost wakeups where a thread sleeps forever despite the state being ready.
Key idea
A condition variable releases its lock and sleeps until signaled, and you must recheck the predicate in a loop because wakeups do not guarantee the condition holds.