0

I have noticed that in most examples of condition variables, I see something like:

pthread_cond_signal(&cond, &lock);
pthread_mutex_unlock(&lock);

My question is why it is done in this order. Why is the signal broadcasted first, before the lock is released? If a context switch occurs in between the signal broadcast and the unlocking, the other threads are woken from sleep and will try to access the lock in question, see that it is still locked, and go back into standby, so won't the signal be wasted?

Why is this not a better solution:

pthread_mutex_unlock(&lock);
pthread_cond_signal(&cond, &lock);

In this case, the lock is released before the threads that are asleep are woken up, so they will actually be able to access the previously locked data.

Can someone clear up this issue for me?

  • @PaulGriffiths the answer in that thread that pertains to my question states "but this can result in less optimal scheduling of threads", but doesn't exactly elaborate on why. – Veme1989 Mar 15 '16 at 00:27
  • The answer from icecrime links to an email from David Butenhof (such information would admittedly be better in the answer itself) which goes into some detail why (and some historical detail as to why that cautionary language was added to the standard). The upshot is, unless you're dealing with real-time performance, there's not really much of an issue signaling or broadcasting without locking the mutex. – Crowman Mar 15 '16 at 00:28
  • The accepted answer to [this question](http://stackoverflow.com/questions/6419117/signal-and-unlock-order) may also be helpful. Some implementations may have a wait queue for the mutex to avoid the kind of superfluous wake-ups you describe. – Crowman Mar 15 '16 at 00:34
  • If you have a crappy implementation that needlessly wakes threads, just use a better implementation. A decent should know that a thread waiting for a condition variable is not ready to run until the associated mutex is released. If the implementation wakes the thread anyway, then presumably there's a reason for that. – David Schwartz Mar 15 '16 at 00:38
  • Also, the solution you think is better is clearly worse, since it has two expensive operations rather than one. Signalling a condition variable while you hold its associated mutex is basically free -- it cannot affect anything else but local state. However, signalling a condition variable while the lock is released requires synchronization and could wake other threads. – David Schwartz Mar 15 '16 at 00:39

2 Answers2

0

The man page has the answer (emphasis mine):

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().

On Freund
  • 4,376
  • 2
  • 23
  • 30
0

I believe you may be onto something.

This is not definitive as it comes from C++'s std::condition_variable, but I believe that it uses the pthread_* calls under the hood: http://en.cppreference.com/w/cpp/thread/condition_variable

From that, in the example section, we have:

// Manual unlocking is done before notifying, to avoid waking up
// the waiting thread only to block again (see notify_one for details)
lk.unlock();
cv.notify_one();
Craig Estey
  • 30,627
  • 4
  • 24
  • 48