Я знал целую вечность, что способ, которым Вы используете условную переменную,
lock
while not task_done
wait on condition variable
unlock
Поскольку иногда условные переменные спонтанно проснутся. Но я никогда не понимал, почему это имеет место. В прошлом я читал, дорого сделать условную переменную, которая не имеет того поведения, но не чего иного как этого.
Так..., почему необходимо волноваться о том, чтобы ложно быть разбуженным при ожидании на условной переменной?
Потоки могут просыпаться без сигналов. Это называется ложным пробуждением . Тем не менее, именно , почему они возникают, - это вопрос, который, кажется, погряз в суевериях и неуверенности. Причины, которые я видел, включают в себя побочный эффект работы реализаций потоков или их намеренное добавление, чтобы заставить программистов правильно использовать циклы вместо условных выражений вокруг wait
.
Дело не в том, что переменная условия будет ошибочно просыпаться; переменная условия будет просыпаться только в том случае, если она получила сигнал от другого потока. Однако возможно, что к тому моменту, когда поток будет перепланирован на выполнение, какой-нибудь другой поток уже успеет занять ресурс, которого вы ждали, и поэтому необходимо перепроверить. Например, если группа потоков x,y,z ожидает некий ресурс R, который ранее был у w, и x,y,z,w обмениваются данными через переменную условия... предположим, что w закончил с R и подает сигнал x,y,z. Таким образом, x, y и z будут выведены из очереди ожидания и помещены в очередь выполнения, чтобы быть запланированными на выполнение. Предположим, что сначала запланирован x... затем он получает R, затем он может быть переведен в спящий режим, затем может быть запланирован y, и когда y будет запущен, ресурс R, на котором ранее ожидал y, все еще недоступен, поэтому необходимо, чтобы y снова перешел в спящий режим. Затем z просыпается, и z также обнаруживает, что R все еще используется, поэтому z нужно снова лечь спать и т.д.
Если у вас ровно два потока, и переменная условия разделяется только между ними двумя, то иногда бывают ситуации, когда можно не выполнять эту проверку. Однако, если вы хотите сделать ваше приложение динамичным и способным масштабироваться до произвольного числа потоков, то хорошо бы иметь привычку (не говоря уже о том, что это гораздо проще и менее хлопотно) выполнять эту дополнительную проверку, поскольку она требуется в большинстве ситуаций.