Вызов сигнала pthread cond без блокировки мьютекса
Я где-то читал, что нужно запереть мьютекс перед вызовом pthread_cond_signal и разблокировать mutext после вызова его:
процедура pthread_cond_signal() является используется для сигнала (или пробуждения) другого поток, который ждет на переменная условия. Это должно быть вызывается после блокировки мьютекса и должен разблокировать мьютекс для pthread_cond_wait() обычной полный.
мой вопрос: не это нормально позвонить pthread_cond_signal или pthread_cond_broadcast методы без блокировки мьютекса?
3 ответов
если вы не заблокируете мьютекс в кодовом пути, который изменяет условие и сигналы, вы можете потерять пробуждения. Рассмотрим эту пару процессов:
Процесс 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
, но процесс a застрял в ожидании переменная состояния-он пропустил сигнал пробуждения. Если мы изменим процесс B, чтобы заблокировать мьютекс:
процесс B (правильный):
pthread_mutex_lock(&mutex);
condition = TRUE;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
...тогда вышеупомянутое не может произойти; пробуждение никогда не будет пропущено.
(обратите внимание, что вы can на самом деле переместить после pthread_mutex_unlock()
, но это может привести к менее оптимальному планированию потоков, и вы обязательно заблокировали мьютекс уже в этом пути кода из-за изменения само условие).
согласно этому руководству :
на
pthread_cond_broadcast()
илиpthread_cond_signal()
функции может вызываться потоком независимо от того, владеет ли он в настоящее время мьютексом что потоки, вызывающиеpthread_cond_wait()
илиpthread_cond_timedwait()
есть связано с переменной condition во время их ожиданий; однако, если предсказуемое поведение планирования требуется, тогда этот мьютекс должен быть заблокирован вызовом потокаpthread_cond_broadcast()
илиpthread_cond_signal()
.
смысл предсказуемое поведение планирование заявление объяснил Дэйв Бутенхоф (автор Программирование с помощью потоков POSIX) на комп.программирование.темы и доступен здесь.
caf, в вашем примере кода, процесс B изменяет condition
без блокировки мьютекса сначала. Если процесс B просто заблокировал мьютекс во время этой модификации, а затем все еще разблокировал мьютекс перед вызовом pthread_cond_signal
, не было бы никаких проблем --- я не ошибся?
я интуитивно верю, что caf позиция правильно: вызов pthread_cond_signal
без владения блокировкой мьютекса-плохая идея. Но КАФ пример на самом деле не является доказательством в поддержку эта позиция; это просто доказательство в поддержку гораздо более слабой (практически самоочевидной) позиции, что это плохая идея изменить общее состояние, защищенное мьютексом, если вы сначала не заблокировали этот мьютекс.
может ли кто-нибудь предоставить пример кода, в котором вызов pthread_cond_signal
затем pthread_mutex_unlock
дает правильное поведение, но вызов pthread_mutex_unlock
следовал по pthread_cond_signal
дает неправильное поведение?