Ich sehe, dass die Frage mit einem Kopfgeld reaktiviert wurde und nun gefragt wird, wozu die praktischen Verwendungszwecke yield
dienen. Ich werde ein Beispiel aus meiner Erfahrung geben.
Wie wir wissen, yield
wird der aufrufende Thread gezwungen, den Prozessor aufzugeben, auf dem er ausgeführt wird, damit die Ausführung eines anderen Threads geplant werden kann. Dies ist nützlich, wenn der aktuelle Thread seine Arbeit vorerst beendet hat, aber schnell zum Anfang der Warteschlange zurückkehren und prüfen möchte, ob sich eine Bedingung geändert hat. Wie unterscheidet sich das von einer Bedingungsvariablen? yield
ermöglicht es dem Thread, viel schneller in einen laufenden Zustand zurückzukehren. Beim Warten auf eine Bedingungsvariable wird der Thread angehalten und muss warten, bis ein anderer Thread signalisiert, dass er fortgesetzt werden soll.yield
Im Grunde heißt es: "Erlaube, dass ein anderer Thread ausgeführt wird, aber erlaube mir, sehr bald wieder an die Arbeit zu gehen, da ich erwarte, dass sich in meinem Zustand sehr schnell etwas ändert." Dies deutet auf ein starkes Spinnen hin, bei dem sich ein Zustand schnell ändern kann, das Anhalten des Threads jedoch zu einem großen Leistungseinbruch führen würde.
Aber genug Geplapper, hier ist ein konkretes Beispiel: das Wellenfront-Parallelmuster. Ein grundlegendes Beispiel für dieses Problem ist die Berechnung der einzelnen "Inseln" von 1s in einem zweidimensionalen Array, das mit 0s und 1s gefüllt ist. Eine "Insel" ist eine Gruppe von Zellen, die entweder vertikal oder horizontal nebeneinander liegen:
1 0 0 0
1 1 0 0
0 0 0 1
0 0 1 1
0 0 1 1
Hier haben wir zwei Inseln von 1s: oben links und unten rechts.
Eine einfache Lösung besteht darin, einen ersten Durchgang über das gesamte Array durchzuführen und die 1-Werte durch einen inkrementierenden Zähler zu ersetzen, sodass am Ende jede 1 durch ihre Sequenznummer in der Hauptreihenfolge ersetzt wurde:
1 0 0 0
2 3 0 0
0 0 0 4
0 0 5 6
0 0 7 8
Im nächsten Schritt wird jeder Wert durch das Minimum zwischen sich und den Werten seiner Nachbarn ersetzt:
1 0 0 0
1 1 0 0
0 0 0 4
0 0 4 4
0 0 4 4
Wir können jetzt leicht feststellen, dass wir zwei Inseln haben.
Der Teil, den wir parallel ausführen möchten, ist der Schritt, in dem wir die Mindestwerte berechnen. Ohne zu sehr ins Detail zu gehen, erhält jeder Thread verschachtelte Zeilen und stützt sich auf die Werte, die von dem Thread berechnet wurden, der die obige Zeile verarbeitet. Daher muss jeder Thread etwas hinter dem Thread zurückbleiben, der die vorherige Zeile verarbeitet, muss aber auch innerhalb einer angemessenen Zeit mithalten. Weitere Details und eine Implementierung werden von mir in diesem Dokument vorgestellt . Beachten Sie, dass die Verwendung sleep(0)
mehr oder weniger dem C-Äquivalent von entspricht yield
.
In diesem Fall yield
wurde verwendet, um jeden Thread nacheinander zum Anhalten zu zwingen. Da jedoch der Thread, der die benachbarte Zeile verarbeitet, in der Zwischenzeit sehr schnell vorrücken würde, würde sich eine Bedingungsvariable als katastrophale Wahl erweisen.
Wie Sie sehen können, yield
handelt es sich um eine ziemlich feinkörnige Optimierung. Wenn Sie es an der falschen Stelle verwenden, z. B. wenn Sie auf einen Zustand warten, der sich selten ändert, wird die CPU übermäßig ausgelastet.
Entschuldigung für das lange Geschwätz, hoffe ich habe mich klar ausgedrückt.