Semantic of pthread_cond_wait
is to release acquired mutex and block on conditional variable. When signal arrives, block is released, then pthread_cond_wait
acquires the lock on mutex.
So, in your case, when you use pthread_cond_broadcast
all threads blocked on conditional will move past this point, but after that one of them will be granted lock on mutex. Which one? It depends on the order the scheduler wakes them up after being unblocked and the pthread implementation in case two or more threads try to acquire the lock at the some moment. It's safe to consider it's random.
If you replace pthread_cond_broadcast
with pthread_cond_signal
, the signal will be delivered to some threads. Yes, it is expected to be one, but sometimes more than one can be released from conditional variable. Still, the thread (or threads) to deliver signal to will be chosen by scheduler. And if more than one is waked up from cond waiting, they will fight for the mutex. As previously - you can consider the result as random.
Let's look into documentation:
If more than one thread is blocked on a condition variable, the scheduling policy shall determine the order in which threads are unblocked.
On a multi-processor, it may be impossible for an implementation of pthread_cond_signal() to avoid the unblocking of more than one thread blocked on a condition variable.
BTW, I am quite curious. There are several questions about conditional variables recently (are you guys all doing a project for your uni or what?) and in every question I have seen in last 24 hours I have seen a following pattern for signalling:
pthread_mutex_lock(&mutex);
pthread_cond_broadcast(&cond); /* or signal */
pthread_mutex_unlock(&mutex);
when waiting threads have:
pthread_mutex_lock(&mutex);
pthread_cond_wait(&cond,&mutex);
/* do something */
pthread_mutex_unlock(&mutex);
What's the reason behind that?
Waiting threads wait on cond
, mutex
is released. So signalling thread acquires lock on mutex
, signals other threads. In this very moment they - still being inside the pthread_cond_wait
progress past the cond
blockade, then they try to acquire the lock on mutex
. And, of course, they cannot, because the lock is hold by signalling thread. Then, signalling thread releases mutex
and waiting threads can finally process by acquiring - one by one - the mutex
.
For signalling writer and waiting consumers this pattern should be as below.
For writer:
while(loop_condition) {
prepare_data() /* it could be a long process */
lock(&mutex);
add_data_to_queue(); /* fast, inside critical section */
unlock(&mutex);
signal(&cond); /* or broadcast */
}
For consumers:
while(consumer_loop_condition) {
lock(&mutex);
while(!data_ready_to_process()) {
wait(&cond,&mutex);
}
fetch_data(); /* fast, still inside critical section */
unlock(&mutex);
if(got_data) {
process_data(); /* could be a long process */
}
}
Please see also this answer for some more explanation on cond/mutexes and some example code to play with.
signal
in the first text is thesignal
in the second (one is an array, the other... not). And even if they are somehow supposed to be the same, theif()
in the second should be under the protection of the mutex, as it contains the predicate state, which is the entire point of the mutex. Wrapping the actual condition notify or broadcast is pointless. The mutex is to protect the predicate; not the cvar. – WhozCraigpthread_const_broadcast()
overpthread_cond_signal()
? – alk