Is possible that a pthread_cond_wait() consumes multiple pthread_cond_signal()?
Asked Answered
D

1

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.

Demagogy answered 10/9, 2015 at 10:43 Comment(0)
T
8

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

Thumping answered 10/9, 2015 at 13:7 Comment(4)
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?)Demagogy
@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.Thumping
@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?Durant
@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).Thumping

© 2022 - 2024 — McMap. All rights reserved.