Если вы не заблокируете мьютекс в пути кода, который изменяет состояние и сигналы, вы можете потерять пробуждение. Рассмотрим эту пару процессов:
Процесс А:
pthread_mutex_lock(&mutex);
while (condition == FALSE)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
Процесс B (неверно):
condition = TRUE;
pthread_cond_signal(&cond);
Затем рассмотрите это возможное чередование инструкций, которое condition
начинается как FALSE
:
Process A Process B
pthread_mutex_lock(&mutex);
while (condition == FALSE)
condition = TRUE;
pthread_cond_signal(&cond);
pthread_cond_wait(&cond, &mutex);
condition
Теперь TRUE
, но процесс А застревают ожидания на переменном состоянии - это пропущенный сигнал пробуждения. Если мы изменим процесс B, чтобы заблокировать мьютекс:
Процесс B (правильный):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
... тогда вышеуказанное не может произойти; пробуждение никогда не будет пропущено.
(Обратите внимание, что вы можете переместить сам pthread_cond_signal()
объект после pthread_mutex_unlock()
, но это может привести к менее оптимальному планированию потоков, и вы обязательно заблокировали мьютекс уже в этом пути кода из-за изменения самого условия).
pthread_signal_cond()
можно переместить после разблокировки мьютекса, хотя, вероятно, лучше этого не делать. Возможно, правильнее будет сказать, что в момент, когда вы вызываетеpthread_signal_cond()
, вам уже нужно было заблокировать мьютекс, чтобы изменить само условие.