Когда любой из них возвращается из pthread_cond_wait (), он автоматически запрашивает мьютекс.
Ах, но это не так. Не «автоматически», то есть в зависимости от того, что означает «автоматически». Вы можете быть смущены "атомарной" семантикой pthread_cond_wait
; но эта семантика воспроизводится на стороне входа: поток каким-то образом регистрируется для ожидания условия перед отказом мьютекса, так что нет никакого окна, в течение которого у потока больше нет мьютекса, и он еще не ожидает на переменную.
Каждый поток, который возвращается из pthread_cond_wait
, должен получить мьютекс и, следовательно, бороться за него. Те, кто проиграл гонку за мьютекс, должны блокировать мьютекс, как если бы они назвали pthread_mutex_lock
.
Способ получения мьютекса при выходе из pthread_cond_wait
можно смоделировать как обычную операцию pthread_mutex_lock
. По сути, потоки должны стоять в очереди на мьютексе, чтобы выйти. Каждый поток, который получает мьютекс, затем возвращается из функции; остальные должны подождать, пока этот поток не откажется от мьютекса, прежде чем им разрешат вернуться.
Никакая нить, пробуждаемая сигналом, не получает мьютекс «автоматически», в смысле передачи права собственности из-за особого права. Во-первых, в многопроцессорном режиме проснувшийся поток может проиграть гонку потоку, уже запущенному на другом процессоре, который захватывает мьютекс, если он доступен, или же очередь, ожидающая мьютекс перед потоком, который получил сигнал. Во-вторых, поток, который вызывает pthread_cond_signal
, может сам не отдать мьютекс и может продолжать его удерживать бесконечно, что означает, что все проснувшиеся потоки будут поставлены в очередь при операции блокировки мьютекса, и ни один из них не появится из pthread_mutex_lock
до этот поток отказывается от мьютекса.
Все, что является «автоматическим», заключается в том, что операция pthread_cond_wait
не возвращается до тех пор, пока снова не будет получен мьютекс, и поэтому приложению не нужно предпринимать шаги для получения мьютекса.