Сделать эту мантру:
Только когда ждать для что-то ...
Ожидание почти всегда выглядеть следующим образом:
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_*
; Возвращаемое значение - важная информация о состоянии, которую вы всегда должны знать, и почти всегда нужно действовать.
Некоторые полезные страницы человека (для возвращаемых значений):
Может быть, вы должны поставить 'pthread_cond_signal' и' pthread_cond_wait' в заголовке, чтобы избегайте путаницы со стандартными функциями C/POSIX 'signal' и' wait'. –