Was genau hat Laufzeit.Gosched tun?
In eine version vor der Version von go 1.5-Tour Gehen websitees ist ein Stück code, das so aussieht.
package main
import (
"fmt"
"runtime"
)
func say(s string) {
for i := 0; i < 5; i++ {
runtime.Gosched()
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}
Die Ausgabe sieht wie folgt aus:
hello
world
hello
world
hello
world
hello
world
hello
Was mich stört, ist, dass, wenn runtime.Gosched()
entfernt wird, wird das Programm nicht mehr gibt "Welt".
hello
hello
hello
hello
hello
Warum ist das so? Wie funktioniert runtime.Gosched()
auf die Ausführung?
InformationsquelleAutor der Frage Jason Yeo | 2012-10-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wenn Sie ausführen, Gehen Sie das Programm ohne die Angabe GOMAXPROCS Umgebungsvariable, Go goroutines geplant sind für die Ausführung in single OS thread. Allerdings, um das Programm angezeigt werden multithreaded (das ist, was goroutines sind, sind Sie nicht?), die Gehen scheduler muss manchmal wechseln Sie den Kontext für die Ausführung, so dass jede goroutine könnte Ihre Arbeit.
Wie gesagt, wenn GOMAXPROCS variable nicht angegeben ist, Gehen runtime ist, darf nur einen thread, so ist es unmöglich zu wechseln ausführungskontexte während goroutine ist die Durchführung einige konventionelle arbeiten, wie Berechnungen oder auch IO (zugeordnete einfache C-Funktionen). Der Rahmen kann gewechselt werden, nur wenn Gehen Parallelität primitive verwendet werden, z.B. beim wechseln auf mehrere chans, oder (das ist dein Fall), wenn Sie explizit den scheduler zu wechseln die Kontexte - das ist, was
runtime.Gosched
ist.Also, kurzum, wenn die Ausführung im Kontext einer goroutine erreicht
Gosched
nennen, der Planer wird beauftragt, schalten Sie die Ausführung zu einem anderen goroutine. In Ihrem Fall gibt es zwei goroutines, main, stellt die "main" - thread des Programms) und weitere, die Sie erstellt haben, mitgo say
. Wenn Sie entfernenGosched
nennen, der Ausführungskontext wird nie übertragen werden, von der ersten goroutine zu der zweiten, also keine 'Welt' für Sie. WennGosched
vorhanden ist, wird der scheduler übergibt die Ausführung jedes loop-iteration von der ersten goroutine zu den zweiten und Umgekehrt, so haben Sie 'Hallo' und 'Welt' interleaved.FYI, dies wird als "kooperatives multitasking': goroutines muss explizit Ertrag die Steuern zu anderen goroutines. Der Ansatz, der in den meisten modernen Betriebssystemen ist genannt 'preemptive multitasking': Ausführungs-threads sind nicht besorgt mit der Kontrolle übertragen; der scheduler schaltet Ausführung Kontexten transparent, um Ihnen statt. Kooperative Ansatz wird Häufig verwendet, um die Implementierung von "green threads", also logische gleichzeitige Coroutinen, die nicht die Karte 1:1 auf OS-threads - das ist wie Go-Laufzeit und seine goroutines umgesetzt werden.
Update
Habe ich erwähnt GOMAXPROCS Umgebungsvariable aber nicht erklären, was es ist. Es ist an der Zeit, dies zu beheben.
Wenn diese variable gesetzt ist, um eine positive Zahl
N
Gehen-runtime-werden in der Lage sein zu erstellen, bis zuN
native threads, auf die alle green threads geplant werden. Native thread-eine Art von thread, die erstellt wird, indem das Betriebssystem (Windows-threads, pthreads, etc). Dies bedeutet, dass, wennN
größer als 1 ist, ist es möglich, dass goroutines zeitgesteuert ausführen in verschiedenen nativen threads und somit parallel ausgeführt werden (zumindest bis zu Ihrem computer Fähigkeiten: wenn Ihr system basiert auf der multicore-Prozessor, ist es wahrscheinlich, dass diese threads wirklich parallel, wenn Ihr Prozessor ist single-core, dann präemptives multitasking realisiert OS-threads erstellen einer Sicht die parallele Ausführung).Ist es möglich, GOMAXPROCS Variablen, die mit
runtime.GOMAXPROCS()
- Funktion anstelle der pre-Einstellung der Umgebungsvariablen. So verwenden Sie in Ihrem Programm anstelle des aktuellenmain
:In diesem Fall können Sie beobachten, interessante Ergebnisse. Es ist möglich, dass Sie 'Hallo' und 'Welt' gedruckten Zeilen interleaved ungleichmäßig, z.B.
Dies kann passieren, wenn goroutines geplant sind, zu gesonderten OS-threads. Dies ist in der Tat, wie präemptives multitasking funktioniert (oder parallel-Verarbeitung im Falle von multicore-Systemen): threads, die parallel sind, und Ihre kombinierte Leistung ist indeterministic. BTW, kann man lassen oder entfernen
Gosched
nennen, es scheint, haben keine Wirkung, wenn GOMAXPROCS ist größer als 1.Folgende ist, was ich habe auf mehreren Durchläufen des Programms mit
runtime.GOMAXPROCS
nennen.Sehen, manchmal die Ausgabe ist schön, manchmal nicht. Indeterminism in Aktion 🙂
Ein weiteres update
Aussieht, dass in neueren Versionen der Go-compiler Gehen runtime Kräfte goroutines Ausbeute nicht nur auf die Parallelität primitive Nutzung, sondern auf OS-system fordert auch. Dies bedeutet, dass die Ausführung der Kontext kann umgeschaltet werden zwischen goroutines auch auf IO-Funktionen aufruft. Folglich ist in den letzten Go-Compiler ist es möglich, zu beobachten, indeterministic Verhalten, selbst wenn GOMAXPROCS nicht gesetzt ist oder den Wert 1.
InformationsquelleAutor der Antwort Vladimir Matveev
Kooperatives scheduling ist der Schuldige. Ohne nachgeben, die anderen (sagen, "Welt") goroutine kann rechtlich bekommen, null Chancen auf ausführen, bevor/wenn main beendet wird, die pro specs beendet alle gorutines - ie. der ganze Prozess.
InformationsquelleAutor der Antwort zzzz