2016-02-18 3 views
1

Я писал код многопоточности с использованием pthread_cond в связке с мьютексами, который заставил меня задуматься:Posix примитивы синхронизации потоков: pthread_cond_signal() и pthread_cond_wait()

  1. является сигнал один раз, так что если сигнал отправляется до того, как другой поток ждет его, другой поток будет продолжать ждать бесконечно?

  2. Так как cond_wait() разблокирует мьютекс, это правило большого пальца, чтобы написать этот оператор JUST перед mutex_unlock(), (я понимаю, что это делает последнее избыточным, но я делаю это только для ясности) или есть много сценариев где вы хотите написать функцию вне блокировки мьютекса?

+0

Может быть, вы должны поставить 'pthread_cond_signal' и' pthread_cond_wait' в заголовке, чтобы избегайте путаницы со стандартными функциями C/POSIX 'signal' и' wait'. –

ответ

1

Сделать эту мантру:

Только когда ждать для что-то ...

Ожидание почти всегда выглядеть следующим образом:

if (pthread_mutex_lock(...) != 0) { 
    /* something terrible happened, panic */ 
} 

while (test-condition) { 
    pthread_cond_wait(...) 
} 

pthread_mutex_unlock(...) 

Если исключительная проверка test-condition не удалась, nd, поэтому контекст входит в pthread_cond_wait, связанный мьютекс будет атомарно разблокирован.

Это означает, что другой контекст может ввести код, который выглядит следующим образом:

if (pthread_mutex_lock(...) != 0) { 
    /* panic */ 
} 

test-condition = false; 

pthread_cond_signal(...); 

pthread_mutex_unlock(...); 

Изменения предиката и атомарно пробуждение первого контекста, который в вызове pthread_cond_wait, который, в свою очередь, проверяет предикат test-condition и может прыгать прошлое петля.

Если мы просто посмотрим на код ожидания снова:

if (pthread_mutex_lock(...) != 0) { 
    /* something terrible happened, panic */ 
} 

while (test-condition) { 
    pthread_cond_wait(...) 
} 

pthread_mutex_unlock(...) 

между вызовом ждать и разблокировать, всегда есть исключительность; Либо потому, что мьютекс был приобретен исключительно (предикатный цикл ожидания не был введен), либо потому, что перед возвратом от вызова к pthread_cond_wait мьютекс был повторно приобретен атомарно.

Синхронизация трудно получить правильно и является дорогостоящей для многопоточного приложения; Следует попытаться сохранить критические разделы просто, чтобы сжать поля для ошибки до их минимального размера.

Еще одна важная вещь - проверить возвращаемые значения всех этих вызовов pthread_*; Возвращаемое значение - важная информация о состоянии, которую вы всегда должны знать, и почти всегда нужно действовать.

Некоторые полезные страницы человека (для возвращаемых значений):

+0

Если вы достаточно параноичны, чтобы проверить возвращаемое значение 'pthread_mutex_lock()' ', почему бы и' pthread_mutex_unlock() 's? – EOF

+0

Это не настоящий код ... правильная проверка ошибок должна выполняться :) –

+0

Я вижу принцип такого использования wait(), но это связано только с параноидальными ситуациями. Что делать, если я хочу использовать его для обычных сценариев? Как http://www.bogotobogo.com/cplusplus/quiz_multithreading.php этот код? –

Смежные вопросы