Goroutine-Ausführungsreihenfolge verstehen
In einem Goroutine-basierten Programm kann die Reihenfolge der Ausführung von Goroutinen unvorhersehbar sein. Dies liegt daran, dass Goroutinen gleichzeitig ausgeführt werden und es keine Garantie gibt, wann oder in welcher Reihenfolge sie ihre Aufgaben erledigen.
Betrachten Sie den folgenden Codeausschnitt:
func sum(a []int, c chan int) { fmt.Println("summing: ", a) total := 0 for _, v := range a { total += v } c <- total // send total to c } func main() { c := make(chan int) go sum([]int{1,2,3}, c) go sum([]int{4,5,6}, c) x := <-c fmt.Println(x) x = <-c fmt.Println(x) }
In diesem Beispiel zwei Goroutinen werden gestartet, um die Summen zweier ganzzahliger Slices zu berechnen. Allerdings ist die Reihenfolge, in der sie ausgeführt und ihre Ergebnisse gedruckt werden, nicht deterministisch. Sie können die Ausgabe wie folgt beobachten:
summing: [4 5 6] 15 summing: [1 2 3] 6
oder
summing: [1 2 3] 6 summing: [4 5 6] 15
Um die Ausführungsreihenfolge von Goroutinen zu synchronisieren, können verschiedene Ansätze verwendet werden:
Using Blockierende Kanäle:
Durch die Nutzung der blockierenden Natur von Kanälen können Sie die Haupt-Goroutine zwingen, auf den Abschluss zu warten jeder Goroutine, bevor Sie mit der nächsten fortfahren. Zum Beispiel:
func main() { c := make(chan int) go sum([]int{1, 2, 3}, c) // Blocks until a value is received x := <-c fmt.Println(x) // Execute the next goroutine go sum([]int{4, 5, 6}, c) x = <-c fmt.Println(x) }
Wartegruppen verwenden:
Eine weitere gängige Synchronisierungstechnik ist die Verwendung von Wartegruppen. Eine Wartegruppe verfolgt die Anzahl der noch laufenden Goroutinen und wartet, bis sie alle abgeschlossen sind, bevor sie fortfährt. So können Sie im obigen Beispiel eine Wartegruppe verwenden:
func sum(a []int, c chan int, wg *sync.WaitGroup) { defer wg.Done() fmt.Println("summing: ", a) total := 0 for _, v := range a { total += v } c <- total // send total to c } func main() { c := make(chan int) wg := new(sync.WaitGroup) // Increment the wait group wg.Add(1) // Launch the first goroutine go sum([]int{1, 2, 3}, c, wg) // Wait for the first goroutine to complete wg.Wait() // Increment the wait group again wg.Add(1) // Launch the second goroutine go sum([]int{4, 5, 6}, c, wg) // Wait for the second goroutine to complete wg.Wait() // Close the channel to indicate that no more values will be sent close(c) // Range over the channel to receive the results for theSum := range c { x := theSum fmt.Println(x) } }
Durch die Integration von Synchronisierungstechniken in Ihren Code erhalten Sie eine bessere Kontrolle über die Reihenfolge, in der Goroutinen ausgeführt werden, und stellen so sicher, dass sie ihre Aufgaben in der ausführen gewünschte Reihenfolge.
Das obige ist der detaillierte Inhalt vonWie kann ich die Ausführungsreihenfolge von Goroutinen in Go steuern?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!