Почему потоки спонтанно просыпаются от ожидания()?

Мне было интересно, почему потоки спонтанно просыпаются от wait() в java.
Это дизайнерское решение? Это компромисс?

EDIT: (из Java Concurrency на практике, стр. 300)

wait даже разрешено возвращать "ложно" - не в ответ на какие-либо уведомление о потоке.

Далее авторы заявляют:

это похоже на тостер с рыхлым соединение, которое заставляет звонок погаснуть когда тост готов, но также иногда, когда он не готов.

Вот почему вы всегда должны кодировать как

synchronized(this){
    while(!condition)
        wait();
    }
}

и никогда

synchronized(this){
    if(!condition){
        wait();
    }
}

Даже если условие переходит только из false до true.

Ответ 1

Эти спонтанные пробуждения также называются "ложными пробуждениями". В спецификации Java ложные пробуждения разрешены (хотя и не поощряются) для реализации jvm.

Причина, по которой они разрешены, заключается в том, что многие реализации могут быть основаны на pthreads (потоки POSIX), которые имеют такое поведение. Почему?

Википедия:

По словам Дэвида Р. Бутенхофа Программирование в потоках POSIX ISBN 0-201-63392-2: "Это означает, что когда вы ждете от переменной условия, ожидание может (иногда) возвращаться, когда нет нить, специально переданная или сигнализировал, что переменная условия. Подвижные пробуждения могут звучать странно, но на некоторых многопроцессорных системах, полное пробуждение состояния предсказуемый может существенно замедлить все операции с переменными состояния. условия гонки, которые вызывают ложные пробуждения следует считать редкими".

Ответ 2

Трудно ответить на этот вопрос окончательно, поскольку спецификация языка Java не указывает, почему реализация JVM может это сделать (она указывает только, что она может, в этом разделе), но я нашел довольно интересную историю ложных пробуждений в Википедии.

Фактическая статья о потоках POSIX, но я не думаю, что это слишком далеко, чтобы предположить, что потоки в Java несколько повлияли на поведение потоков POSIX:

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

Эта цитата из Дэвида Р. Бутенхофа, который затем продолжает:

Несмотря на то, что действительно были некоторые члены рабочей группы, которые утверждали, что теоретически можно предположить, что такая реализация может быть такой, на самом деле это не причина. (И они так и не смогли это доказать.) Нити POSIX стали результатом напряженности между прагматичными программистами в реальном времени и в основном академическими исследователями. Поддельные пробуждения - это механизм академической клирики, чтобы убедиться, что каждый должен написать чистый код, который проверял и проверял предикаты!

"Но (возможно) в значительной степени ложный (или, по крайней мере, арканистический философский) аргумент" эффективности "перешел лучше с людьми в реальном времени, и реальная причина обычно отводилась на второе место в обосновании.

" Я много раз думал о том, как вы могли бы создать правильную и практичную реализацию, которая действительно имела бы поддельные пробуждения. Мне никогда не удалось создать пример. Не означает, что нет ни одного, и это хорошая история.