Java Thread notify() против notifyAll()

Я немного смущен Java notify(), Следующий пример взят из учебника.

public synchronized consume() {
    while(queue.isEmpty()) {
        try{ wait(); } catch (InterruptedException e) {}
    }
    // Assume that getElement() notifies to producers.
    element = queue.getElement();
    ...
}

public synchronized produce() {
    while(queue.isFull()) {
        try{ wait(); } catch (InterruptedException e) {}
    }
    element = new Element();
    ...
    queue.addElement(element);
    notifyAll();
}

Я вполне понимаю метод produce() в приведенном выше примере. Однако, может кто-нибудь сказать мне, почему мы не используем notifyAll() в конце первого метода (consume())? Для краткости, почему бы не так:

public synchronized consume() {
    while(queue.isEmpty()) {
        try{ wait(); } catch (InterruptedException e) {}
    }
    // Assume that getElement() notifies to producers.
    element = queue.getElement();
    ...
    notifyAll();
}

Большое спасибо!

С наилучшими пожеланиями.

2 ответа

Решение

Я согласен с вами @Slash. В вашем примере кода, так как вы удаляете элемент из очереди, тогда кто-то должен уведомить производителей, ожидающих в isEmpty() петля. Код, однако, говорит:

// Assume that getElement() notifies to producers.
element = queue.getElement();

Так что этот комментарий означает, что как-то getElement() звонки notify() или же notifyAll(),

Для краткости, почему бы не так:

Да, ваш код будет работать, хотя вам нужно удалить комментарий.:-)

Обычно в этих шаблонах производитель / потребитель есть две блокировки: одна, когда очередь пуста, и одна, если она заполнена. Затем потребители могут сигнализировать производителям, когда очередь больше не заполнена, и не разбудить других потребителей. В этом случае также вы можете использовать один notify() так как вам нужно разбудить только одного потребителя или одного производителя. notifyAll() используется здесь, потому что существует только один объект synchronized на.

Кроме того, для потомков очень важно, чтобы вы заметили while() петли не if заявления. Даже когда вы используете notify() и две блокировки - это условия гонки в модели нескольких производителей / потребителей, которые должны быть защищены. Также ложные пробуждения являются проблемой. Подробнее об этом здесь:

http://256stuff.com/gray/docs/misc/producer_consumer_race_conditions/

В этом случае уведомление используется при производстве, чтобы сообщить потребителям, что теперь есть что потреблять, чтобы один из них мог проснуться и потребить его.

Предполагается, что уведомление, когда потребитель только что что-то потребил, происходит внутри getElement():

// Assume that getElement() notifies to producers.
Другие вопросы по тегам