Maison > développement back-end > Golang > Pourquoi les canaux sans tampon dans Go provoquent-ils des blocages ?

Pourquoi les canaux sans tampon dans Go provoquent-ils des blocages ?

Mary-Kate Olsen
Libérer: 2024-12-21 17:31:11
original
226 Les gens l'ont consulté

Why Do Unbuffered Channels in Go Cause Deadlocks?

Interblocage dans les canaux sans tampon dans les Goroutines

Dans le modèle de concurrence de Go, les canaux sans tampon peuvent conduire à des blocages inattendus. Voyons pourquoi cela se produit et explorons une solution alternative.

Considérez l'extrait de code suivant :

package main

import "fmt"

func main() {
    c := make(chan int)    
    c <- 1   
    fmt.Println(<-c)
}
Copier après la connexion

Ce code effectue apparemment une simple opération d'envoi et de réception sur un canal sans tampon. Cependant, une fois exécuté, il entraîne un blocage avec l'erreur suivante :

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /home/tarrsalah/src/go/src/github.com/tarrsalah/tour.golang.org/65.go:8 +0x52
exit status 2
Copier après la connexion

Pour comprendre pourquoi ce blocage se produit, nous devons d'abord comprendre le comportement des canaux sans tampon.

Plonger dans les canaux sans tampon

Comme indiqué dans la documentation officielle de Go, "Si le canal est sans tampon, l'expéditeur bloque jusqu'à ce que le récepteur ait reçu la valeur. Si le canal a un tampon, l'expéditeur bloque uniquement jusqu'à ce que la valeur ait été copiée dans le tampon. Si le tampon est plein, cela signifie attendre qu'un récepteur ait récupéré une valeur. ."

En termes plus simples :

  1. Les canaux sans tampon sont considérés comme perpétuellement pleins.
  2. Envoi de données à un canal sans tampon bloque l'expéditeur jusqu'à ce qu'un autre goroutine récupère la valeur.

Le scénario de blocage

Dans l'extrait de code fourni, l'opération c <- 1 bloque car le canal n'est pas tamponné et aucun autre goroutine n'existe pour recevoir la valeur envoyée. Par conséquent, le programme se bloque.

Sortir de l'impasse

Pour sortir de l'impasse, nous pouvons soit :

  1. Utiliser un Canal tamponné : En créant un canal tamponné (par exemple, c := make(chan int, 1)), nous allouer un petit tampon où les goroutines de l'expéditeur peuvent temporairement placer des valeurs avant qu'un récepteur ne soit prêt.

OU

  1. Introduire une goroutine de réception : Nous pouvons introduire un goroutine séparé pour gérer la réception des données du canal. Cela garantit qu'un consommateur est toujours disponible pour récupérer les valeurs envoyées.

Exemple avec une Goroutine réceptrice :

package main

import "fmt"

func main() {
    c := make(chan int)    
    go func() {
        fmt.Println("received:", <-c)
    }()
    c <- 1   
}
Copier après la connexion

Ici, la goroutine créée avec go func() {...} attendra continuellement de recevoir les valeurs du canal. En introduisant cette goroutine de réception, le blocage est évité.

En conclusion, l'utilisation de canaux non tamponnés dans la même goroutine sans mécanisme de réception dédié peut conduire à des blocages. Pour éviter cela, envisagez d'utiliser des canaux mis en mémoire tampon ou d'introduire des goroutines de réception distinctes pour garantir un transfert de données approprié entre les goroutines simultanées.

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 de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal