Если вы не блокируете мьютекс в кодексе, который изменяет состояние и сигналы, вы можете потерять пробуждения. Рассмотрю эту пару процессов:
Процесса A:
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 (правильный):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
... то выше, может не произойти; пробуждение никогда не будет пропущено.
(Обратите внимание, что вы можете фактически переместить сам pthread_cond_signal()
после pthread_mutex_unlock()
, но это может привести к снижению оптимального планирования потоков, и вы обязательно заперта мьютекс уже в этом коде пути из-за изменения самого состояния).
имеет смысл! спасибо :) – Meysam
@Nemo: Да, на «правильном» пути «pthread_signal_cond()' * can * может быть перемещен после разблокировки мьютекса, хотя, вероятно, лучше не делать этого. Возможно, правильнее сказать, что в тот момент, когда вы вызываете 'pthread_signal_cond()', вам уже необходимо заблокировать мьютекс, чтобы изменить само условие. – caf
@Nemo: Да, код сломан, поэтому он помечен как «неправильный» - мой опыт заключается в том, что люди, которые задают этот вопрос, часто рассматривают возможность полного блокирования на сигнальном пути. Возможно, ваш опыт отличается. – caf