Java Thread notify()与notifyAll()

时间:2012-04-12 00:34:23

标签: java multithreading asynchronous synchronized monitors

我对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 个答案:

答案 0 :(得分:6)

我同意你@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/

答案 1 :(得分:1)

在这种情况下,通知在生成时使用,告诉消费者现在有东西要消耗,以便其中一个可以唤醒并消费它。

通知消费者刚刚消费了什么东西,假设发生在getElement():

// Assume that getElement() notifies to producers.