Это просто способ, которым переменные условия (или были изначально) реализованы.
Мьютекс используется для защиты самой переменной условия . Вот почему вам нужно заблокировать его, прежде чем ждать.
Ожидание «атомарно» разблокирует мьютекс, предоставляя другим доступ к переменной условия (для сигнализации). Затем, когда переменная условия будет сигнализирована или передана, один или несколько потоков в списке ожидания будут разбужены, и мьютекс снова будет магически заблокирован для этого потока.
Обычно вы видите следующую операцию с условными переменными, иллюстрирующую их работу. В следующем примере показан рабочий поток, которому дается работа через сигнал условной переменной.
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
do the work.
unlock mutex.
clean up.
exit thread.
Работа выполняется в этом цикле при условии, что некоторые из них будут доступны после возвращения ожидания. Когда поток помечен как прекращающий работу (обычно другой поток устанавливает условие выхода, а затем запускает переменную условия, чтобы разбудить этот поток), цикл завершается, мьютекс разблокируется и этот поток завершается.
Приведенный выше код является моделью для одного потребителя, так как мьютекс остается заблокированным во время работы. Для варианта с несколькими потребителями вы можете использовать, например :
thread:
initialise.
lock mutex.
while thread not told to stop working:
wait on condvar using mutex.
if work is available to be done:
copy work to thread local storage.
unlock mutex.
do the work.
lock mutex.
unlock mutex.
clean up.
exit thread.
что позволяет другим потребителям получать работу, пока этот делает работу.
Переменная условия освобождает вас от бремени опроса некоторого условия, позволяя другому потоку уведомлять вас, когда что-то должно произойти. Другой поток может сказать, что этот поток доступен следующим образом:
lock mutex.
flag work as available.
signal condition variable.
unlock mutex.
Подавляющее большинство из того, что часто ошибочно называют ложными пробуждениями, как правило, всегда происходило из-за того, что в их pthread_cond_wait
вызове (широковещании) было сигнализировано несколько потоков , можно было вернуться с мьютексом, выполнить работу, а затем снова подождать.
Тогда вторая сигнальная нить могла выйти, когда не было никакой работы. Таким образом, у вас должна была быть дополнительная переменная, указывающая, что работа должна быть выполнена (это было изначально защищено мьютексом с помощью пары condvar / mutex - другие потоки должны были заблокировать мьютекс перед тем, как его изменить).
Это было технически возможно для нити , чтобы вернуться из состояния ожидания , не выгоняют другой процесс (это является подлинным поддельным будильником) , но во всех мои многих годах работают над Pthreads, как в развитии услуг / коды и как пользователь из них я ни разу не получил ни одного из них. Может быть, это только потому, что у HP была достойная реализация :-)
В любом случае, тот же код, который обрабатывал ошибочный случай, также обрабатывал подлинные ложные пробуждения, так как для них не был установлен флаг доступности работы.