Allerdings wird (wenn ich den Unterschied zwischen diesen Methoden richtig verstehe) immer nur ein Thread für die weitere Monitor-Erfassung ausgewählt.
Das ist nicht richtig. o.notifyAll()
weckt alle der Threads, die in den folgenden Bereichen blockiert sind o.wait()
Anrufe. Die Threads dürfen nur zurückkehren von o.wait()
einer nach dem anderen, aber sie alle wird an die Reihe kommen.
Ganz einfach: Es hängt davon ab, warum Ihre Threads auf eine Benachrichtigung warten. Wollen Sie einem der wartenden Threads mitteilen, dass etwas passiert ist, oder wollen Sie alle gleichzeitig informieren?
In einigen Fällen können alle wartenden Threads nützliche Aktionen durchführen, sobald die Wartezeit beendet ist. Ein Beispiel wäre eine Gruppe von Threads, die auf die Beendigung einer bestimmten Aufgabe warten; sobald die Aufgabe beendet ist, können alle wartenden Threads mit ihrer Arbeit fortfahren. In einem solchen Fall würden Sie Folgendes verwenden notifyAll() um alle wartenden Threads gleichzeitig aufzuwecken.
In einem anderen Fall, z. B. bei einer sich gegenseitig ausschließenden Sperre, kann nur einer der wartenden Threads etwas Sinnvolles tun, nachdem er benachrichtigt wurde (in diesem Fall die Sperre übernehmen). In einem solchen Fall sollten Sie lieber notify() . Richtig umgesetzt, können Sie podría verwenden. notifyAll() auch in dieser Situation, aber Sie würden unnötigerweise Threads aufwecken, die ohnehin nichts tun können.
In vielen Fällen wird der Code, der eine Bedingung abwarten soll, als Schleife geschrieben:
synchronized(o) {
while (! IsConditionTrue()) {
o.wait();
}
DoSomethingThatOnlyMakesSenseWhenConditionIsTrue_and_MaybeMakeConditionFalseAgain();
}
Auf diese Weise kann, falls ein o.notifyAll()
Aufruf mehr als einen wartenden Thread auf, und der erste, der vom o.wait()
die Bedingung im falschen Zustand belässt, werden die anderen Threads, die geweckt wurden, wieder in den Wartezustand versetzt.
6 Stimmen
Die nützlichen Bibliotheken für die Gleichzeitigkeit sind in den Gleichzeitigkeitsbibliotheken zu finden. Ich schlage vor, dass diese in fast jedem Fall die bessere Wahl sind. Die Concurency-Bibliotheken stammen aus der Zeit vor Java 5.0 (wo sie 2004 als Standard hinzugefügt wurden)
4 Stimmen
Ich bin anderer Meinung als Peter. Die Gleichzeitigkeitsbibliothek ist in Java implementiert, und jedes Mal, wenn Sie lock(), unlock() usw. aufrufen, wird eine Menge Java-Code ausgeführt. Man kann sich in den Fuß schießen, wenn man die Gleichzeitigkeitsbibliothek anstelle der guten alten
synchronized
außer für bestimmte, eher seltene Anwendungsfälle.4 Stimmen
Das Hauptmissverständnis scheint folgendes zu sein: ... wird immer nur ein Thread für die weitere Monitor-Erfassung ausgewählt; im ersten Fall der von der VM, im zweiten Fall der vom System-Thread-Scheduler ausgewählte. Dies impliziert, dass sie im Wesentlichen gleich sind. Das beschriebene Verhalten ist zwar korrekt, aber es fehlt, dass in der
notifyAll()
Fall bleiben _die anderen Threads nach dem ersten wach und übernehmen den Monitor, einer nach dem anderen. In demnotify
Fall wird keiner der anderen Threads aufgeweckt. Funktionell sind sie also sehr unterschiedlich!0 Stimmen
1) Wenn viele Threads auf ein Objekt warten und notify() nur einmal für dieses Objekt aufgerufen wird. Außer einem der wartenden Threads warten die übrigen Threads ewig? 2) Wenn notify() verwendet wird, beginnt nur einer der vielen wartenden Threads mit der Ausführung. Wenn notifyall() verwendet wird, werden alle wartenden Threads benachrichtigt, aber nur einer von ihnen beginnt mit der Ausführung, was ist also der Nutzen von notifyall() hier?
1 Stimmen
@ChetanGowda Die Benachrichtigung aller Threads im Vergleich zur Benachrichtigung genau eines beliebigen Threads hat tatsächlich einen signifikanten Unterschied, bis uns dieser scheinbar subtile, aber wichtige Unterschied auffällt: Wenn Sie nur einen Thread benachrichtigen(), befinden sich alle anderen Threads im Wartezustand, bis sie eine explizite Benachrichtigung/ein Signal erhalten. Wenn Sie alle benachrichtigen, werden alle Threads in einer bestimmten Reihenfolge nacheinander ohne weitere Benachrichtigung ausgeführt und abgeschlossen - hier sollten wir sagen, dass die Threads
blocked
und nichtwaiting
.wennblocked
wird seine Ausführung vorübergehend ausgesetzt, bis sich ein anderer Thread innerhalb dersync
Block.