Heim >Backend-Entwicklung >Golang >Wie kann ich die Ausführungsreihenfolge von Goroutinen in Go steuern?

Wie kann ich die Ausführungsreihenfolge von Goroutinen in Go steuern?

Susan Sarandon
Susan SarandonOriginal
2024-12-12 16:54:10866Durchsuche

How Can I Control the Execution Order of Goroutines in Go?

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!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn