Why do we need a condition check before pthread_cond_wait
You need a while loop because the thread that called pthread_cond_wait
might wake up even when the condition you are waiting for isn't reached. This phenomenon is called "spurious wakeup".
This is not a bug, it is the way the conditional variables are implemented.
This can also be found in man pages:
Spurious wakeups from the pthread_cond_timedwait() or pthread_cond_wait() functions may occur. Since the return from pthread_cond_timedwait() or pthread_cond_wait() does not imply anything about the value of this predicate, the predicate should be re-evaluated upon such return.
Update regarding the actual code:
void* proc_add(void *name) { struct vars *my_data = (struct vars*)name; printf("In thread Addition and my id = %d\n",pthread_self()); while(1) { pthread_mutex_lock(&mutexattr); while(!my_data->ipt){ // If no input get in pthread_cond_wait(&mutexaddr_add,&mutexattr); // Wait till signalled } my_data->opt = my_data->a + my_data->b; my_data->ipt=1; pthread_cond_signal(&mutexaddr_opt); pthread_mutex_unlock(&mutexattr); if(my_data->end) pthread_exit((void *)0); } }}
You must test the condition under the mutex before waiting because signals of the condition variable are not queued (condition variables are not semaphores). That is, if a thread calls pthread_cond_signal()
when no threads are blocked in pthread_cond_wait()
on that condition variable, then the signal does nothing.
This means that if you had one thread set the condition:
pthread_mutex_lock(&m);cond = true;pthread_cond_signal(&c);pthread_mutex_unlock(&m);
and then another thread unconditionally waited:
pthread_mutex_lock(&m);pthread_cond_wait(&c, &m);/* cond now true */
this second thread would block forever. This is avoided by having the second thread check for the condition:
pthread_mutex_lock(&m);if (!cond) pthread_cond_wait(&c, &m);/* cond now true */
Since cond
is only modified with the mutex m
held, this means that the second thread waits if and only if cond
is false.
The reason a while ()
loop is used in robust code instead of an if ()
is because pthread_cond_wait()
does not guarantee that it will not wake up spuriously. Using a while ()
also means that signalling the condition variable is always perfectly safe - "extra" signals don't affect the program's correctness, which means that you can do things like move the signal outside of the locked section of code.