2012-04-12 4 views
2

Я немного смущен Java notify(). Следующий пример из учебника.Java Thread notify() vs. notifyAll()

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(); 
} 

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

С уважением.

ответ

6

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

// 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/

+0

Большое спасибо, Серый. :-) –

1

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

Уведомление, когда потребитель только потребляли то, как предполагается, произойдет внутри getElement():

// Assume that getElement() notifies to producers. 
+0

@dlev правильно, см редактирования. – EJP

+0

Спасибо, приятель. :-) –