Middle
Was ist Laufzeit (Runtime) und wie funktioniert der Scheduler?
sobes.tech KI
Antwort von AI
Die Laufzeitumgebung (runtime) in Go ist die Umgebung, in der Go-Programme ausgeführt werden. Sie umfasst:
- Speicherverwaltung: Der Garbage Collector verwaltet automatisch die Zuweisung und Freigabe von Speicher.
- Scheduler: Verwalten die Ausführung von Goroutines auf Betriebssystem-Threads.
- Systemaufrufe: Bieten eine Schnittstelle zur Interaktion mit dem Betriebssystem.
- Synchronisationsprimitive: Kanäle, Mutexes und andere Mechanismen zur Koordination von Goroutines.
Der Go-Scheduler implementiert das M:N-Modell (viele Goroutines auf vielen Betriebssystem-Threads). Seine Hauptkomponenten:
- G (Goroutine): Ein leichter Ausführungsthread, im Wesentlichen eine Abstraktion einer Funktion.
- M (Machine): Ein Betriebssystem-Thread, auf dem Go-Programme ausgeführt werden.
- P (Processor): Ein logischer Prozessor, der mit einem Betriebssystem-Thread verbunden ist. Er hält eine lokale
runnable-Warteschlange für Goroutines.
Funktionsprinzip des Schedulers:
- Goroutines (G) werden erstellt und in eine globale oder lokale
runnable-Warteschlange eingefügt. - Betriebssystem-Threads (M) werden mit logischen Prozessoren (P) assoziiert. Die Anzahl der P entspricht standardmäßig der Anzahl der CPU-Kerne (
GOMAXPROCS). - P nimmt eine Goroutine aus seiner lokalen Warteschlange. Wenn die lokale Warteschlange leer ist, versucht P, Goroutines von einer anderen P oder der globalen Warteschlange "zu stehlen".
- M führt die Goroutine aus.
- Wenn eine Goroutine blockiert (z.B. beim Lesen aus einem Kanal ohne Daten oder bei einem Systemaufruf), trennt sich M von P, und P wird für die Ausführung einer anderen Goroutine verfügbar. Die blockierte Goroutine wird in Wartestellung versetzt. Wenn die Blockierung aufgehoben wird, wird die Goroutine wieder
runnableund in die Warteschlange eingereiht. - Wenn M bei einem Systemaufruf blockiert, hält es P nicht fest. Es kann ein neues M erstellt oder ein bestehendes verwendet werden, damit P andere Goroutines ausführen kann.
Dieser Ansatz ermöglicht eine effiziente Nutzung der Prozessorressourcen und eine einfache Skalierung paralleler Aufgaben, wobei die Komplexität der Betriebssystem-Thread-Verwaltung vor dem Entwickler verborgen bleibt.
// Beispiel für die Erstellung einer Goroutine
func myFunc() {
// Goroutine-Code
}
func main() {
go myFunc() // Start der Goroutine
// Das Hauptprogramm läuft parallel weiter
}