简体   繁体   中英

Java Thread notify( ) vs. notifyAll()

I am confused a bit by Java's notify() . The following example is from a textbook.

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

I quite understand the method produce() in the above example. However, can anyone tell me why we do not use notifyAll() at the end of the first method ( consume() )? For short, why not like this:

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

Thanks a lot!

Best regards.

I agree with you @Slash. In your code example, since you are removing and element from the queue then someone needs to notify the producers which are waiting in the isEmpty() loop. You code however says:

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

So that comment means that somehow getElement() calls notify() or notifyAll() .

For short, why not like this:

Yes, your code would work although you need to remove the comment. :-)

Typically in these producer/consumer patterns, there are two locks: one when the queue is empty and one if it is full. Then the consumers can signal the producers when the queue is no longer full and not wake up the other consumers. In this case also, you could use a single notify() since you only need to awaken a single consumer or a single producer. The notifyAll() is used here because there is only one object being synchronized on.

Also, for posterity, it is very important that you notice the while() loops are not if statements. Even when you are using notify() and two locks there are race conditions in a multiple producer/consumer model that have to be protected against. Also spurious wakeups are an issue. More on that here:

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

In this case the notification is used when producing, to tell consumers that there is now something to consume, so that one of them can wake up and consume it.

Notifying when a consumer has just consumed something is assumed to happen inside getElement():

// Assume that getElement() notifies to producers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM