Почему вызов wait() принято помещать в цикл while, а не в if?
Пробуждение не гарантирует, что условие выполнено: возможны ложные пробуждения (spurious wakeup), а между notify и захватом монитора другой поток мог снова изменить состояние. Поэтому условие перепроверяют в while.
- notify лишь переводит поток в очередь на монитор
- notifyAll безопаснее notify, если ждут по разным условиям
- То же правило для Condition.await
А ещё В новом коде — BlockingQueue и другие готовые примитивы вместо wait/notify
Подробно
Вторая причина важнее первой и часто выпадает из ответа: notify лишь переводит поток в очередь на монитор, а захватить его он сможет только после освобождения — за это время другой поток вполне может войти и снова нарушить условие. Поэтому проснувшийся обязан перепроверить состояние, а значит нужен цикл. Полезно тут же назвать связанные факты: wait освобождает монитор, а sleep — нет; вызывать wait и notify можно только владея монитором, иначе IllegalMonitorStateException; notifyAll безопаснее notify, потому что notify может разбудить не того ждущего и привести к зависанию. В современном коде вместо этой пары обычно берут Condition или готовые примитивы из java.util.concurrent.
Пример
synchronized (lock) {
while (queue.isEmpty()) {
lock.wait();
}
return queue.poll();
}Что хотят услышать
- Обе причины: ложные пробуждения и перехват состояния.
- Готовые примитивы как замена.
Частые ошибки
- Использовать if вместо while.
- Предпочитать notify вместо notifyAll без строгого обоснования.
Проверьте себя
Один верный вариант. Подумайте, потом откройте ответ.
Показать варианты и ответ
- ✗Потому что wait() нужно вызывать несколько раз подряд для надёжности
- ✗Потому что if не компилируется внутри synchronized-блока
- ✓Возможны ложные пробуждения, а условие могло измениться, пока поток ждал монитор
- ✗Чтобы монитор отпускался между проверками и другие потоки успевали работать
Что спросят дальше
- Чем wait отличается от sleep по владению монитором?
- Почему notifyAll обычно безопаснее notify?
Разбор темы
- synchronized, мониторы и wait/notify
Взаимное исключение и видимость через монитор, reentrancy, guarded blocks с wait/notify и причины deadlock.
Связанные вопросы
Разбор собеседования с sotto
После собеседования sotto разбирает разговор: оценка, каждый вопрос — хорошо, частично или слабо, чего не хватило в ответе и над чем поработать к следующему разу. Первые 30 минут бесплатно.