Maison >développement back-end >Golang >Comment puis-je contrôler l'ordre d'exécution des Goroutines dans Go ?

Comment puis-je contrôler l'ordre d'exécution des Goroutines dans Go ?

Susan Sarandon
Susan Sarandonoriginal
2024-12-12 16:54:10866parcourir

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

Comprendre l'ordre d'exécution des goroutines

Dans un programme basé sur les goroutines, l'ordre d'exécution des goroutines peut être imprévisible. En effet, les goroutines sont exécutées simultanément et il n'y a aucune garantie quand et dans quel ordre elles termineront leurs tâches.

Considérez l'extrait de code suivant :

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)
}

Dans cet exemple, deux goroutines sont lancés pour calculer les sommes de deux tranches entières. Cependant, l'ordre dans lequel ils sont exécutés et leurs résultats sont imprimés n'est pas déterministe. Vous pouvez observer le résultat comme :

summing:  [4 5 6]
15
summing:  [1 2 3]
6

ou

summing:  [1 2 3]
6
summing:  [4 5 6]
15

Pour synchroniser l'ordre d'exécution des goroutines, diverses approches peuvent être utilisées :

En utilisant Chaînes bloquantes :

En utilisant la nature bloquante des chaînes, vous pouvez forcer la goroutine principale à attendre pour l'achèvement de chaque goroutine avant de passer à la suivante. Par exemple :

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)
}

Utilisation de groupes d'attente :

Une autre technique de synchronisation courante consiste à utiliser des groupes d'attente. Un groupe d'attente garde une trace du nombre de goroutines encore en cours d'exécution et attend qu'elles soient toutes terminées avant de continuer. Voici comment utiliser un groupe d'attente dans l'exemple ci-dessus :

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)
    }

}

En incorporant des techniques de synchronisation dans votre code, vous obtenez un meilleur contrôle sur l'ordre dans lequel les goroutines s'exécutent, garantissant ainsi qu'elles accomplissent leurs tâches dans le séquence souhaitée.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn