Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is possible that a pthread_cond_wait() consumes multiple pthread_cond_signal()?

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.

like image 329
Pacheco Avatar asked Sep 10 '15 10:09

Pacheco


1 Answers

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

like image 63
caf Avatar answered Sep 21 '22 14:09

caf