Это просто способ, которым условные переменные (или были изначально) реализованы.
Мьютекс используется для защиты самой переменной условия . Вот почему вам нужно заблокировать его перед ожиданием.
Ожидание «атомно» разблокирует мьютекс, предоставляя другим доступ к переменной условия (для сигнализации). Затем, когда переменная условия будет сигнализирована или передана, один или несколько потоков в списке ожидания будут разбужены, и мьютекс снова будет магически заблокирован для этого потока.
Обычно вы видите следующую операцию с условными переменными, иллюстрирующую, как они работают. В следующем примере показан рабочий поток, которому дается работа через сигнал условной переменной.
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 - другие потоки должны были заблокировать мьютекс перед тем, как его изменить).
* * * * * * * * * * * * * * * * * * * * технически возможно *1030* для потока, чтобы вернуться из условия ожидания, не будучи запущенным другим процессом (это - подлинное ложное пробуждение), но, за все мои многие годы работы над pthreads, оба в разработке / службы кода и, как пользователь их, я никогда не получал один из них. Может быть, это потому, что у HP была достойная реализация: -)
В любом случае, тот же код, который обрабатывал ошибочный случай, также обрабатывал подлинные ложные пробуждения, так как для них не был установлен флаг доступности работы.