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 ?

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 ?

DDD
DDDoriginal
2024-10-29 21:49:29583parcourir

Why does the Go program print the sum of the computation before the message in the given code snippet, even though the main goroutine blocks until a signal is received from the channel?

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 :

  1. main crée les goroutines.
  2. Le le planificateur sélectionne l'affichage, qui imprime le message et attend une réponse.
  3. Le planificateur passe à sum, qui s'exécute pendant une longue période.
  4. Le planificateur revient à l'affichage, qui envoie le signal .
  5. Le planificateur passe au principal, qui imprime le signal et quitte.

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!

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