Conditional variables are useful in cases where you want a thread to wait for something that happens in another thread. For instance, in a producer/consumer scenario with one or or more producing threads and one consuming thread, conditional variables can be used to signal the consuming thread that new data is available.
General process
A wait on a conditional variable (queueCond in the producer/consumer example) is always coupled to a mutex (the queueMutex in the producer/consumer example), and should always be coupled to a "normal" state variable also (queue.empty() in the producer/consumer example). When used correctly, this ensures that no new data is missed in the consumer.
In general, the process should be:
while
loop on the state variable, looping as long as the data is not readywhile
loop, do a wait on the condition variable with pthread_cond_wait()
while
loop exits, we are now sure that new data is ready, and that the mutex is lockedWith this scheme, no matter when the signalling and waiting threads are scheduled, the waiting thread will never miss data (as in, it will never be stuck waiting forever with valid data ready). This can be realized by manually trying to run through the steps for the signalling thread, recording the states of the mutex, condition and state variables, for each of the steps in the waiting thread.
pthread_cond_wait
and the mutex
To facilitate the above process, it is required to call pthread_cond_wait()
with the mutex locked. When called, pthread_cond_wait()
will then unlock the mutex before putting the thread to sleep, and, just before returning for whatever reason, the mutex will be relocked. This also means that if some other thread currently has the mutex locked, pthread_cond_wait()
will wait for the mutex to be unlocked, and until the waiting thread can actually acquire the mutex - it will contend on it together with any other threads trying to lock the mutex at the same time.
Spurious wakeups
Also, it may seem as if the while
loop waiting on the state variable could be substituted for a simple if
statement. However, the while
loop is needed, as the Posix standard allows pthread_cond_wait()
to do so-called "spurious" wakeups during the wait, without actually being signalled. Thus, the code needs to recheck the state variable to see if pthread_cond_wait()
returned due to actually being signalled, or due to one of these spurious wakeups.