Maison >développement back-end >Golang >Pourquoi l'envoi et la réception sur un canal sans tampon dans la même goroutine provoquent-ils un blocage dans Go ?

Pourquoi l'envoi et la réception sur un canal sans tampon dans la même goroutine provoquent-ils un blocage dans Go ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-23 01:20:15964parcourir

Why Does Sending and Receiving on an Unbuffered Channel in the Same Goroutine Cause a Deadlock in Go?

Comprendre les blocages dans Go simultané : canal sans tampon au sein d'une Goroutine

Dans le modèle de concurrence de Go, les canaux sont un outil crucial pour la communication entre les goroutines. Cependant, une utilisation inappropriée des canaux peut entraîner des blocages, comme illustré dans cet extrait de code :

package main

import "fmt"

func main() {
    c := make(chan int)  
    c <- 1   
    fmt.Println(<-c)
}

Une fois exécuté, ce code entraîne un blocage avec le message d'erreur suivant :

fatal error: all goroutines are asleep - deadlock!

Pourquoi ce blocage se produit-il ?

Le problème réside dans l'utilisation d'un canal sans tampon au sein du même goroutine. Les canaux sans tampon n'ont pas de stockage interne, ce qui signifie que l'envoi d'une valeur à un canal sans tampon est bloqué jusqu'à ce qu'un autre goroutine lise la valeur.

Dans ce cas, le goroutine envoie une valeur au canal c et tente de recevoir une valeur du canal c. même canal de manière séquentielle. Puisqu'il n'y a pas d'autre goroutine pour recevoir la valeur, la goroutine de l'expéditeur se bloque indéfiniment, ce qui entraîne un blocage.

Comment pouvez-vous y remédier ?

Il existe deux solutions :

  1. Créez une chaîne tamponnée : En créant une chaîne avec un buffer, vous autorisez le stockage de plusieurs valeurs avant de bloquer la goroutine de l'expéditeur. Par exemple :
c := make(chan int, 1) 

Cela crée un canal avec une taille de tampon de 1, permettant de stocker une valeur sans blocage.

  1. Utilisez un canal distinct goroutine pour l'envoi : Au lieu d'envoyer dans la même goroutine, créez une goroutine distincte pour envoyer les valeurs au canal. Par exemple :
package main

import "fmt"

func main() {
    c := make(chan int)    
    go func() {
        c <- 1
    }()
    fmt.Println(<-c)
}

Dans cet exemple, la goroutine de l'expéditeur envoie une valeur au canal c de manière asynchrone. La goroutine principale reçoit ensuite la valeur du canal sans rencontrer de blocage.

Comprendre le comportement des canaux sans tampon et éviter une utilisation inappropriée est essentiel pour écrire des programmes Go simultanés efficaces et non bloquants.

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