Maison > développement back-end > Golang > le corps du texte

Pourquoi le code Go fourni avec WaitGroup et le canal mis en mémoire tampon entraîne-t-il un blocage ?

Barbara Streisand
Libérer: 2024-10-26 22:08:02
original
680 Les gens l'ont consulté

Why does the provided Go code with WaitGroup and buffered channel result in a deadlock?

Deadlocks dans Go avec WaitGroup et Buffered Channels

Dans Go, un blocage se produit lorsque plusieurs goroutines s'attendent les unes les autres pour se terminer, ce qui entraîne dans une impasse. Cette situation peut survenir lors d'une utilisation incorrecte des canaux mis en mémoire tampon et des WaitGroups.

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

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

Ce code est censé créer un canal avec une taille de tampon de 4 et démarrer 5 goroutines. , chacun envoyant une tranche vide au canal. La goroutine principale attend que toutes les goroutines aient terminé, puis parcourt le canal.

Cependant, ce code entraînera une impasse. Pourquoi ?

Cause de l'impasse :

Deux problèmes existent dans le code :

  1. Capacité du canal : Le canal a une capacité de 4, ce qui signifie qu'il peut contenir jusqu'à 4 éléments. Cependant, 5 goroutines tentent d'envoyer au canal, ce qui entraîne une situation où la dernière goroutine bloquera en attendant qu'un emplacement soit libéré.
  2. Fermeture du canal : la boucle range ch continue d'attendre des éléments. pour accéder à la chaîne. Puisqu'il n'y a plus de goroutines à écrire sur la chaîne, la boucle attendra indéfiniment.

Solutions :

  1. Augmenter la capacité du canal : En augmentant la capacité du canal à 5, suffisamment d'emplacements seront disponibles pour que toutes les goroutines envoient leurs valeurs sans blocage. De plus, fermer le canal une fois que les goroutines ont fini d'écrire signalera à la boucle de portée qu'aucun autre élément n'arrive, l'empêchant d'attendre indéfiniment.

    <code class="go">ch := make(chan []int, 5)
    ...
    wg.Wait()
    close(ch)</code>
    Copier après la connexion
  2. Utiliser Terminé () dans la boucle : Au lieu de fermer le canal, on peut utiliser la méthode Done() de WaitGroup pour signaler quand la dernière goroutine est terminée. En appelant Done() dans la boucle de plage, la goroutine principale sera avertie lorsque le canal est vide et la boucle pourra se terminer.

    <code class="go">go func() {
        for c := range ch {
            fmt.Printf("c is %v\n", c)
            wg.Done()
        }
    }()
    wg.Wait()</code>
    Copier après la connexion

Ces solutions résolvent l'impasse en garantissant que le canal a une capacité suffisante et que la boucle de plage se termine lorsqu'il n'y a plus d'éléments à lire dans le canal.

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
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!