Maison > développement back-end > Golang > Comment puis-je éviter les blocages lors de l'utilisation de WaitGroups et de canaux mis en mémoire tampon dans Go ?

Comment puis-je éviter les blocages lors de l'utilisation de WaitGroups et de canaux mis en mémoire tampon dans Go ?

Linda Hamilton
Libérer: 2024-10-26 18:10:02
original
408 Les gens l'ont consulté

How can I prevent deadlock when using WaitGroups and buffered channels in Go?

Interblocage dans Go : groupe d'attente et canaux tamponnés

Dans Go, un blocage se produit lorsque des goroutines concurrentes attendent indéfiniment la fin de l'autre. Une cause fréquente de blocage implique l'utilisation de WaitGroups et de canaux mis en mémoire tampon.

Exemple de blocage

Considérez le code suivant :

<code class="go">package main

import "fmt"
import "sync"

func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            ch <- m // Sending to a full channel
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>
Copier après la connexion

Ce code vise à envoyer 5 tranches vides à un canal tamponné d'une capacité de 4, puis à lire à partir du canal une fois toutes les goroutines terminées. Cependant, le code entraîne une erreur de blocage.

Cause du blocage

Le blocage est dû à deux problèmes :

  1. Tampon de canal insuffisant : Le canal a une capacité de 4, ce qui est trop petit pour les 5 goroutines essayant d'envoyer des données. Lorsque le canal est plein, les goroutines suivantes attendant d'envoyer des données (ligne 15) se bloqueront indéfiniment.
  2. Itération du canal bloquant : La boucle qui parcourt le canal (lignes 22 à 24) se bloque indéfiniment car il attend que d'autres éléments arrivent sur la chaîne. Étant donné que toutes les goroutines ont fini d'envoyer des données et qu'aucune donnée supplémentaire n'est attendue, cette itération ne se terminera jamais sans une lecture de goroutine correspondante du canal.

Solution

Pour résoudre l'impasse, effectuez l'une des modifications suivantes :

Solution 1 :

Augmentez la capacité du canal à 5 ​​(ou plus) et fermez-le après l'envoi de toutes les données :

<code class="go">ch := make(chan []int, 5)
...
wg.Wait()
close(ch)</code>
Copier après la connexion

Solution 2 :

Démarrez une goroutine distincte pour lire à partir du canal et avertissez la goroutine principale lorsque toutes les données ont été reçues :

<code class="go">func main() {
    ch := make(chan []int, 4)
    var m []int

    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            ch <- m
            wg.Done()
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()
}</code>
Copier après la connexion

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!

source:php.cn
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