7

I've tested this scenario in some environments, and I got the following flow:

expected

However, from the man pages ( http://linux.die.net/man/3/pthread_cond_wait ) or ( http://linux.die.net/man/3/pthread_cond_signal ), I cannot find any guarantee that the following scenario cannot happen:

scenario

Which is that 2 threads doing a signal can run before any waiting thread has the chance to run. (scheduling possibility)

[Now, I know that if this was done with semaphores, the second scenario would never happen... however in my case I really need to do this with cond-vars!]

In my case every post increments the predicate, so when the waiting Thread2 wakes-up it will check the predicate (which in this case was incremented by 2), making the thread to not sleep anymore and it would decrement the predicate by 1 (meaning that one post was consumed).

If this scenario can happen, it would imply that the "Thread1" might not wake up until a further post happens, although the predicate was incremented twice (post) and decremented only once (the Thread2 wait). Even worse, a 3rd wait might never block as it would consume the previous-pending predicate increment.

I could not yet trigger this problem, but does anyone know if this is a possible scenario?


NOTE to overcome this possibility I've replaced the pthread_cond_signal() by pthread_cond_broadcast() so both the Thread1 and Thread2 are guaranteed to wake up and consume the 2 increments. However, this solution decreases a bit (maybe not even significantly) the performance, and I bet it is not obvious to anyone looking at this why we are using broadcasts here.

Community
  • 1
  • 1
Pacheco
  • 133
  • 7

1 Answers1

9

No, it is not possible for one pthread_cond_wait() to consume two signals.

pthread_cond_signal() is guaranteed to wake up at least one thread that is currently waiting on the condition variable. Once a thread has been signalled, it is no longer waiting on the condition variable (though it may still be waiting on the associated mutex), so a subsequent pthread_cond_signal() must awaken a different waiting thread (if there are any).

(In your second diagram, the second signal must target a thread other than Thread2, because Thread2 is no longer waiting on the condition variable at that point).

The exact wording in the POSIX spec for pthread_cond_signal is:

The pthread_cond_signal() function shall unblock at least one of the threads that are blocked on the specified condition variable cond (if any threads are blocked on cond).

caf
  • 233,326
  • 40
  • 323
  • 462
  • Thanks for the answer. I was assuming that a thread was blocked until the moment of execution (moment where it tries to acquire the mutex). So is there a mechanism on the OS to "tag" the threads? (meaning each pthread_cond_signal() will "untag" a different thread?) – Pacheco Sep 10 '15 at 13:55
  • 1
    @Pacheco: It depends on the OS how it's implemented, but generally the processes blocked on the condition variable will be in a wait queue, and signalling the condition variable will atomically move one process off that queue. – caf Sep 10 '15 at 14:17
  • @caf, sir, both caf and the POSIX standards say that _`pthread_cond_signal()` is guaranteed to wake up **at least one** thread that is currently waiting on the condition variable._ So, can `pthread_cond_signal()` make more than one thread to wake up? What does **at least one** mean? I have thought until now the function makes only one thread to wake up at a time. I'm confused somewhat. Would you mind elucidating? – Soner from The Ottoman Empire May 01 '19 at 10:37
  • 1
    @snr: Yes, `pthread_cond_signal()` is allowed to wake up more than one thread. `pthread_cond_signal()` is an optimisation - any correct program could replace each use of `pthread_cond_signal()` with `pthread_cond_broadcast()` and remain correct (although the reverse is *not* true). – caf May 01 '19 at 13:36