Вопрос проверяет понимание мониторов объектов и правил безопасной синхронизации потоков.
Нет, вызывать wait() и notify() вне synchronized-блока нельзя.
Если попытаться это сделать, будет выброшено IllegalMonitorStateException.
Это связано с тем, что данные методы работают только с монитором объекта.
Поток должен владеть монитором, чтобы управлять ожиданием других потоков.
Так Java защищает модель синхронизации от ошибок.
Чтобы понять причину ограничения, нужно сначала разобраться, как работает монитор объекта.
synchronizedОпределение:
Монитор объекта — это механизм, который гарантирует, что только один поток в момент времени выполняет код, защищённый synchronized.
Перед началом вызова wait() или notify() поток обязан:
Захватить монитор объекта.
Работать внутри synchronized (obj) или синхронизированного метода.
Если вызвать:
lock.wait();
без synchronized, JVM:
Проверяет, владеет ли поток монитором lock.
Обнаруживает, что монитор не захвачен.
Выбрасывает IllegalMonitorStateException.
Это сделано для того, чтобы:
Исключить гонки данных.
Гарантировать атомарность проверки условий.
Обеспечить корректное освобождение и повторный захват монитора.
Корректный шаблон:
synchronized (lock) {
while (!condition) {
lock.wait();
}
}
wait() и notify() нельзя вызывать вне synchronized, потому что они управляют монитором объекта, а доступ к монитору возможен только при его захвате.