Maison >développement back-end >Golang >Pourquoi l'utilisation de canaux sans tampon dans Go entraîne-t-elle une impasse ?

Pourquoi l'utilisation de canaux sans tampon dans Go entraîne-t-elle une impasse ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-12-18 16:55:10321parcourir

Why Does Using Unbuffered Channels in Go Lead to Deadlock?

Impasse dans le modèle de concurrence Go : utilisation de canaux sans tampon

Dans le modèle de concurrence Go, les canaux sont un mécanisme fondamental pour la communication entre les goroutines . Cependant, le comportement des canaux peut varier en fonction de la taille de leur tampon. Ici, nous abordons un scénario de blocage qui survient lors de l'utilisation de canaux sans tampon.

Le problème

Considérez l'extrait de code Go suivant :

package main

import "fmt"

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

Une fois exécuté, ce code génère un impasse :

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /path/to/file:8 +0x52
exit status 2

Explication

L'impasse se produit en raison de l'utilisation d'un canal sans tampon. Un canal sans tampon, comme l'indique la documentation, nécessite la présence d'un récepteur avant qu'une valeur puisse être envoyée. Dans ce cas, le canal est initialisé comme sans tampon par défaut (avec une taille de tampon de 0).

Lorsque la ligne c <- 1 est exécutée, la goroutine tente d'envoyer la valeur 1 sur le canal. Cependant, comme le canal n'a pas de tampon, il attend qu'un récepteur récupère la valeur avant de continuer.

Simultanément, l'instruction fmt.Println(<-c) tente de recevoir une valeur du canal. Cependant, comme aucune valeur n'a encore été envoyée (car la goroutine attend un récepteur), l'opération de réception se bloque.

Cela entraîne une impasse, car les deux goroutines attendent que l'autre termine une opération ni l'une ni l'autre. peut fonctionner sans l'autre.

Solution

Pour sortir de l'impasse, il faut introduire un récepteur pour la chaîne. En créant une goroutine distincte pour gérer la réception de la valeur envoyée, le blocage peut être éliminé. Le code modifié ci-dessous illustre cette solution :

package main

import "fmt"

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

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