Because of the mutex locks, it doesn't matter if you do it before or after the signal, because the variable cannot be read until the mutex is unlocked.
condition variables signaling
-
05-12-2021 - |
Domanda
In this link here, in the increment function, condition variable is signalled before actually incrementing the count(from zero). Should the signal be not invoked after incrementing the count? Or does the wait call in decrement_count function not return until the mutex is released in increment_function?
pthread_mutex_t count_lock;
pthread_cond_t count_nonzero;
unsigned count;
decrement_count()
{
pthread_mutex_lock(&count_lock);
while (count == 0)
pthread_cond_wait(&count_nonzero, &count_lock);
count = count - 1;
pthread_mutex_unlock(&count_lock);
}
increment_count()
{
pthread_mutex_lock(&count_lock);
if (count == 0)
pthread_cond_signal(&count_nonzero);
count = count + 1;
pthread_mutex_unlock(&count_lock);
}
Soluzione
Altri suggerimenti
As Troy says, signalling the condition variable before incrementing counter
is fine, because these actions are both done with the mutex held.
However, this code does have a subtle bug if multiple threads can be waiting in decrement_count()
. Consider the case where two threads are suspended in pthread_cond_wait()
, with count == 0
. Now, increment_count()
is called twice in succession (perhaps by the same thread) - count
is incremented to 2
, as it should be, but the condition variable is only signalled once. This means that only one of the waiting threads is woken, and the other will wait indefinitely even though counter
is nonzero.
This bug can be fixed in several ways:
- replace
pthread_cond_signal()
withpthread_cond_broadcast()
inincrement_count()
; or - unconditionally call
pthread_cond_signal()
inincrement_count()
; or - call
pthread_cond_signal()
ifcount
is nonzero after decrementing indecrement_count()
.
In general, remember that using pthread_cond_signal()
instead of pthread_cond_broadcast()
is an optimisation, and you should carefully analyse whether the algorithm is still correct when using it.