Вызов сигнала 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 дает неправильное поведение?