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!