Maison >développement back-end >Golang >Pourquoi le programme Go imprime-t-il la somme du calcul avant le message dans l'extrait de code donné, même si la goroutine principale se bloque jusqu'à ce qu'un signal soit reçu du canal ?
Concurrence Go et confusion des canaux
Dans Go, la concurrence permet à plusieurs tâches de s'exécuter simultanément à l'aide de goroutines. Les canaux facilitent la communication entre ces goroutines. Cependant, comprendre la simultanéité peut être difficile, en particulier lorsqu'il s'agit de canaux.
Considérez l'extrait de code suivant :
<code class="go">package main import "fmt" func display(msg string, c chan bool) { fmt.Println("display first message:", msg) c <- true } func sum(c chan bool) { sum := 0 for i := 0; i < 10000000000; i++ { sum++ } fmt.Println(sum) c <- true } func main() { c := make(chan bool) go display("hello", c) go sum(c) <-c }</code>
Dans ce code, nous créons deux goroutines : affichage et somme. La goroutine d'affichage imprime un message, envoie un signal au canal, puis attend une réponse. La goroutine somme effectue un long calcul, imprime le résultat et envoie également un signal au canal. Dans la goroutine principale, nous bloquons jusqu'à ce qu'un signal soit reçu du canal.
La sortie attendue du code est :
display first message: hello
Cependant, nous observons que le programme imprime à la fois le message et la somme du calcul :
display first message: hello 10000000000
Comprendre le problème
Le problème se pose en raison de la nature non déterministe de la planification des goroutines. Le planificateur de Go choisit librement entre les goroutines qui ne sont pas bloquées. Dans cet exemple, le planificateur peut exécuter n'importe laquelle des goroutines à tout moment.
Un ordre d'exécution possible est :
Dans ce scénario, la somme est imprimée avant que l'affichage n'envoie le signal, ce qui entraîne une sortie inattendue.
Solution
Pour garantir que le programme imprime uniquement le message et se termine avant que la somme ne soit calculée, nous pouvons utiliser une approche différente :
<code class="go">func main() { result := make(chan string) go display("hello", result) go sum(result) fmt.Println(<-result) }</code>
Dans cette version révisée, le canal résultat porte une seule valeur, le message de la goroutine d'affichage. La goroutine principale imprime désormais la valeur du canal, s'assurant qu'elle reçoit le message avant de quitter.
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!