В Java-программе с использованием wait()/notify() опубликован следующий паттерн: if (queue.isEmpty()) queue.wait(); /* затем обработка */ — опишите проблему с потерянным сигналом и гонкой, и предложите безопасный шаблон использования ожидания с условием и синхронизацией?

27 Мар в 17:24
24 +1
0
Ответы
1
Проблема (коротко):
- Потерянный сигнал: если проверка условия и вызов `wait()` не выполняются атомарно относительно `notify()` (например проверка вне синхронизации или используется `if` + `notify()` от другого потока), то поток может пропустить уведомление — уведомление произойдёт до того, как поток начнёт ждать, и тогда поток повиснет навсегда.
- Гонка / неверная реакция после пробуждения: даже если `wait()` вызван корректно под монитором, спорадические пробуждения и конкуренция нескольких потребителей означают, что после пробуждения условие могло уже не выполняться. Использование `if` вместо `while` приведёт к тому, что пробуждённый поток продолжит обработку при уже ложном условии.
Безопасный шаблон (синхронизация + цикл проверки):
- Используйте общий монитор (обычно тот же объект `queue`) и проверяйте условие в цикле `while`.
- Производитель должен уведомлять (`notifyAll()` предпочтительнее, если несколько ожидающих потоков).
Пример с монитором `queue`:
synchronized (queue) {
while (queue.isEmpty()) {
queue.wait();
}
Object item = queue.remove();
}
// обработка item вне синхронизованного блока при желании
Производитель:
synchronized (queue) {
queue.add(item);
queue.notifyAll(); // notifyAll предпочтительнее при множественных слушателях
}
Альтернатива с Lock/Condition:
final Lock lock = new ReentrantLock();
final Condition notEmpty = lock.newCondition();
lock.lock();
try {
while (queue.isEmpty()) {
notEmpty.await();
}
Object item = queue.remove();
} finally {
lock.unlock();
}
Производитель:
lock.lock();
try {
queue.add(item);
notEmpty.signalAll();
} finally {
lock.unlock();
}
Рекомендация: по возможности используйте готовые классы из java.util.concurrent (например, BlockingQueue), они реализуют безопасную проверку/ожидание и избавляют от этих ошибок.
27 Мар в 18:31
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир