Ложная разблокировка в буст-ветке - PullRequest
10 голосов
/ 09 марта 2009

Я наткнулся на этот интересный абзац в документации Boost Thread сегодня:

void wait(boost::unique_lock<boost::mutex>& lock)

...

Эффекты: атомный вызов lock.unlock () и блокирует текущий поток. поток будет разблокирован при получении уведомления от вызовите это-> notify_one () или this-> notify_all () или spuriful . Когда нить разблокирована (для по какой-либо причине), замок восстановлен путем вызова lock.lock () перед вызовом ожидания возвращается. замок также восстанавливается путем вызова lock.lock (), если функция завершается с исключение.

Итак, меня интересует значение слова «с энтузиазмом». Почему поток был заблокирован по ложным причинам? Что можно сделать, чтобы решить эту проблему?

Ответы [ 2 ]

11 голосов
/ 09 марта 2009

Эта статья Энтони Уильямса особенно подробна.

Ложные следы не могут быть предсказаны: они по существу случайны из точка зрения пользователя. Тем не менее, они обычно происходит, когда поток библиотеки не может надежно гарантировать, что ожидание Тема не пропустит уведомление. Поскольку пропущенное уведомление сделать переменную условия бесполезной, библиотека потоков будит поток от его ожидания, а не взять риск.

Он также указывает, что вы не должны использовать перегрузки timed_wait, которые занимают какое-то время, и вы должны обычно использовать версии, которые принимают предикат

Это ошибка новичка, и один это легко преодолеть с помощью простого правило: всегда проверяйте свой предикат в цикл при ожидании с условием переменная. Более коварная ошибка из timed_wait ().

Эта статья Владимира Пруса тоже интересна.

Но зачем нам цикл while, мы не можем написать:

if (!something_happened)
  c.wait(m);

Мы не можем. И причина убийства в том, что «ждать» может вернуться без какого-либо вызова «уведомить». Это называется ложным пробуждением и является явно разрешено POSIX. По сути, возврат только из «ожидания» указывает, что общие данные могут изменились, так что данные должны быть оценивается снова.

Хорошо, так почему это еще не исправлено? Первая причина в том, что никто не хочет починить это. Завершение вызова «ждать» в петля очень желательна для нескольких другие причины. Но эти причины требуют объяснений, в то время как поддельные пробуждение - это молоток, который можно применить любому первокурснику без потерпеть неудачу.

2 голосов
/ 09 марта 2009

В этом блоге приводится причина для Linux в виде системного вызова futex, возвращаемого при доставке сигнала процессу. К сожалению, это ничего не объясняет (и действительно требует дополнительной информации).

Запись в Википедии о ложных пробуждениях (которая, по-видимому, является концепцией всего посиса, кстати, не ограничивается повышением) также может вас заинтересовать.

...