Jeśli nie zablokujesz muteksu w ścieżce kodowej, która zmienia stan i sygnały, możesz utracić wybudzenia. Rozważ tę parę procesów:
Proces A:
pthread_mutex_lock(&mutex);
while (condition == FALSE)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
Proces B (nieprawidłowy):
condition = TRUE;
pthread_cond_signal(&cond);
Następnie rozważ możliwość przeplotu instrukcji, gdzie condition
zaczyna się jako FALSE
:
Process A Process B
pthread_mutex_lock(&mutex);
while (condition == FALSE)
condition = TRUE;
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
condition
Jest teraz TRUE
, ale jest zablokowany Proces A czeka na zmiennej warunkowej - to brakowało sygnał wzbudzenia. Jeśli zmienimy Proces B, aby zablokować muteks:
Proces B (poprawny):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
... wtedy powyższe nie może wystąpić; przebudzenie nigdy nie zostanie pominięte.
(Zauważ, że możesz faktycznie przenieść to pthread_cond_signal()
samo po znaku pthread_mutex_unlock()
, ale może to spowodować mniej optymalne planowanie wątków i koniecznie zablokowałeś muteks już w tej ścieżce kodu z powodu zmiany samego warunku).
pthread_signal_cond()
można przesunąć po odblokowaniu mutexa, chociaż prawdopodobnie lepiej tego nie robić. Być może bardziej poprawne jest stwierdzenie, że w momencie, w którym dzwoniszpthread_signal_cond()
, będziesz musiał już zablokować muteks, aby zmodyfikować sam warunek.