Calling pthread_cond_signal without locking mutex
C++PthreadsMutexSignalsCondition VariableC++ Problem Overview
I read somewhere that we should lock the mutex before calling pthread_cond_signal and unlock the mutex after calling it:
> The pthread_cond_signal() routine is > used to signal (or wake up) another > thread which is waiting on the > condition variable. It should be > called after mutex is locked, and must > unlock mutex in order for > pthread_cond_wait() routine to > complete.
My question is: isn't it OK to call pthread_cond_signal or pthread_cond_broadcast methods without locking the mutex?
C++ Solutions
Solution 1 - C++
If you do not lock the mutex in the codepath that changes the condition and signals, you can lose wakeups. Consider this pair of processes:
Process A:
pthread_mutex_lock(&mutex);
while (condition == FALSE)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
Process B (incorrect):
condition = TRUE;
pthread_cond_signal(&cond);
Then consider this possible interleaving of instructions, where condition
starts out as FALSE
:
Process A Process B
pthread_mutex_lock(&mutex);
while (condition == FALSE)
condition = TRUE;
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
The condition
is now TRUE
, but Process A is stuck waiting on the condition variable - it missed the wakeup signal. If we alter Process B to lock the mutex:
Process B (correct):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
...then the above cannot occur; the wakeup will never be missed.
(Note that you can actually move the pthread_cond_signal()
itself after the pthread_mutex_unlock()
, but this can result in less optimal scheduling of threads, and you've necessarily locked the mutex already in this code path due to changing the condition itself).
Solution 2 - C++
According to this manual :
> The pthread_cond_broadcast()
or
> pthread_cond_signal()
functions
> may be called by a thread whether or not it currently owns the mutex that
> threads calling pthread_cond_wait()
> or pthread_cond_timedwait()
have
> associated with the condition variable
> during their waits; however, if
> predictable scheduling behavior is
> required, then that mutex shall be
> locked by the thread calling
> pthread_cond_broadcast()
or
> pthread_cond_signal()
.
The meaning of the predictable scheduling behavior statement was explained by Dave Butenhof (author of Programming with POSIX Threads) on comp.programming.threads and is available here.
Solution 3 - C++
caf, in your sample code, Process B modifies condition
without locking the mutex first. If Process B simply locked the mutex during that modification, and then still unlocked the mutex before calling pthread_cond_signal
, there would be no problem --- am I right about that?
I believe intuitively that caf's position is correct: calling pthread_cond_signal
without owning the mutex lock is a Bad Idea. But caf's example is not actually evidence in support of this position; it's simply evidence in support of the much weaker (practically self-evident) position that it is a Bad Idea to modify shared state protected by a mutex unless you have locked that mutex first.
Can anyone provide some sample code in which calling pthread_cond_signal
followed by pthread_mutex_unlock
yields correct behavior, but calling pthread_mutex_unlock
followed by pthread_cond_signal
yields incorrect behavior?