2

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

非常感谢!

最好的祝福。

4

2 回答 2

6

我同意你的看法@Slash。在您的代码示例中,由于您要从队列中删除元素,因此需要有人通知正在isEmpty()循环中等待的生产者。但是,您的代码说:

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

因此,该评论意味着以某种方式getElement()调用notify()or notifyAll()

简而言之,为什么不这样:

是的,尽管您需要删除评论,但您的代码可以工作。:-)

通常在这些生产者/消费者模式中,有两种锁:一种在队列为空时,另一种在队列已满时。然后消费者可以在队列不再满时向生产者发出信号,并且不会唤醒其他消费者。在这种情况下,您也可以使用单个notify(),因为您只需要唤醒单个消费者或单个生产者。在notifyAll()这里使用 是因为只有一个对象在synchronized上。

此外,对于后代来说,注意到循环不是语句非常重要。即使您使用两个锁,在多生产者/消费者模型中也存在竞争条件,必须加以保护。虚假唤醒也是一个问题。更多关于这里:while() ifnotify()

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

于 2012-04-12T00:37:44.447 回答
1

在这种情况下,通知在生产时使用,告诉消费者现在有东西要消费,以便他们中的一个人可以醒来并消费它。

假设在 getElement() 内部发生了消费者刚刚消费完某物时的通知:

// Assume that getElement() notifies to producers.
于 2012-04-12T00:37:36.373 回答