Looking for java Keywords? Try Ask4Keywords

Java Language Pitfall: неправильное использование wait () / notify ()


пример

Методы object.wait() , object.notify() и object.notifyAll() предназначены для использования очень определенным образом. (см. http://stackoverflow.com/documentation/java/5409/wait-notify#t=20160811161648303307 )

Проблема «потерянного оповещения»

Одна общая ошибка начинающего заключается в том, чтобы безоговорочно вызвать object.wait()

private final Object lock = new Object();

public void myConsumer() {
    synchronized (lock) {
        lock.wait();     // DON'T DO THIS!!
    }
    doSomething();
}

Причина, по которой это неверно, заключается в том, что в зависимости от какого-то другого потока можно вызвать lock.notify() или lock.notifyAll() , но ничто не гарантирует, что другой поток не сделал этот вызов перед потребительским потоком, называемым lock.wait() .

lock.notify() и lock.notifyAll() ничего не делать вообще , если какой -либо другой поток уже не дожидаясь уведомления. Поток, который вызывает myConsumer() в этом примере, будет зависать вечно, если слишком поздно поймать уведомление.

Ошибка «Недопустимое состояние монитора»

Если вы вызываете wait() или notify() на объект, не удерживая блокировку, тогда JVM будет IllegalMonitorStateException .

public void myConsumer() {
    lock.wait();      // throws exception
    consume();
}

public void myProducer() {
    produce();
    lock.notify();    // throws exception
}

(Конструкция wait() / notify() требует блокировки, потому что это необходимо для того, чтобы избежать системных условий гонки. Если бы можно было вызвать wait() или notify() без блокировки, тогда было бы невозможно реализовать основной пример использования этих примитивов: ожидание возникновения условия.)

Ожидание / уведомление слишком низкоуровневое

Лучший способ избежать проблем с wait() и notify() - не использовать их. Большинство проблем синхронизации можно решить, используя объекты синхронизации более высокого уровня (очереди, барьеры, семафоры и т. Д.), Которые доступны в пакете java.utils.concurrent .