Maison >développement back-end >Golang >Comment éviter les blocages dans Go lorsque vous utilisez WaitGroup et un canal avec un tampon limité ?

Comment éviter les blocages dans Go lorsque vous utilisez WaitGroup et un canal avec un tampon limité ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-10-27 01:21:021050parcourir

How can you avoid deadlock in Go when using WaitGroup and a channel with a limited buffer?

Impasse dans Go avec WaitGroup et Channel

Dans Go, une impasse se produit lorsque deux goroutines ou plus attendent indéfiniment que l'autre termine. Dans cet exemple, nous explorerons un problème de blocage causé par un tampon de canal insuffisant et une synchronisation incorrecte des goroutines à l'aide d'un WaitGroup.

Le code

<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
            return
        }()
    }
    wg.Wait()

    for c := range ch {
        fmt.Printf("c is %v", c)
    }
}</code>

Le problème

Le code tente d'envoyer 5 valeurs sur un canal tamponné de taille 4. Cependant, lorsque le canal est plein, il se bloque jusqu'à ce qu'un récepteur devienne disponible. Puisque toutes les goroutines qui envoient sont terminées, aucune n'est disponible pour recevoir du canal.

De plus, la goroutine qui s'étend sur le canal (pour c := range ch) reste également bloquée indéfiniment car elle attend plus de valeurs pour arriver dans le canal même si aucun autre message n'est envoyé. Cela crée une impasse dans laquelle les expéditeurs et les destinataires s'attendent les uns les autres.

Solution 1 : Augmentez la mémoire tampon du canal et fermez-la

Une solution pour éviter l'impasse consiste à augmentez la taille du tampon du canal à une valeur supérieure ou égale au nombre de goroutines d'envoi. De plus, le canal doit être fermé une fois tous les envois terminés, indiquant qu'aucune autre valeur ne sera reçue.

<code class="go">ch := make(chan []int, 5)
...
wg.Wait()
close(ch)</code>

Solution 2 : Effectuer Done() dans la réception de Goroutine

Une autre solution consiste à exécuter Done() dans la goroutine de réception plutôt que dans la fonction principale. Ce faisant, le WaitGroup ne sera pas décrémenté tant que la valeur n'aura pas été reçue et consommée par la goroutine :

<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
            return
        }()
    }
    go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()
}</code>

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