2012-04-12 10 views
2

Ich bin ein wenig verwirrt von Java notify(). Das folgende Beispiel stammt aus einem Lehrbuch.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(); 
} 

Ich verstehe durchaus die Methode produce() in dem obigen Beispiel. Kann mir aber jemand sagen, warum wir notifyAll() am Ende der ersten Methode (consume()) nicht verwenden? Kurz, warum nicht wie folgt:

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

Vielen Dank!

Mit freundlichen Grüßen.

Antwort

6

Ich stimme Ihnen zu @Slash. Da Sie in Ihrem Codebeispiel ein Element aus der Warteschlange entfernen, muss jemand die Hersteller benachrichtigen, die in der Schleife isEmpty() warten. Sie Code jedoch sagt:

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

Damit Kommentar bedeutet, dass irgendwie getElement() Anrufe notify() oder notifyAll().

Für kurze, warum dies nicht mag:

Ja, würde Ihr Code arbeiten, obwohl Sie den Kommentar entfernen müssen. :-)

Normalerweise gibt es in diesen Producer/Consumer-Mustern zwei Sperren: eine, wenn die Warteschlange leer ist, und eine, wenn sie voll ist. Dann können die Verbraucher den Erzeugern signalisieren, wenn die Schlange nicht mehr voll ist und die anderen Verbraucher aufwecken und nicht aufwecken. In diesem Fall können Sie auch eine einzelne notify() verwenden, da Sie nur einen einzelnen Verbraucher oder einen einzelnen Hersteller wecken müssen. Die notifyAll() wird hier verwendet, da nur ein Objekt synchronized aktiviert ist.

Auch für die Nachwelt ist es sehr wichtig, dass Sie die while() Schleifen nichtif Aussagen bemerken. Selbst wenn Sie notify() und zwei Sperren verwenden, gibt es in einem Modell mit mehreren Herstellern/Konsumenten Race-Bedingungen, gegen die geschützt werden muss. Auch falsche Wakeups sind ein Problem. Mehr dazu hier:

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

+0

Vielen Dank, Grey. :-) –

1

In diesem Fall wird die Benachrichtigung beim Produzieren verwendet, um den Konsumenten mitzuteilen, dass jetzt etwas zu konsumieren ist, so dass einer von ihnen aufwachen und es konsumieren kann.

Mitteile, wenn ein Verbraucher nur etwas verbraucht hat, wird davon ausgegangen, innerhalb getElement passieren():

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

@dlev richtig finden bearbeiten. – EJP

+0

Danke, Kumpel. :-) –

Verwandte Themen