Calling pthread_cond_signal without locking mutex

C++PthreadsMutexSignalsCondition Variable

C++ 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?

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionB FaleyView Question on Stackoverflow
Solution 1 - C++cafView Answer on Stackoverflow
Solution 2 - C++icecrimeView Answer on Stackoverflow
Solution 3 - C++QuuxplusoneView Answer on Stackoverflow