Maison  >  Article  >  développement back-end  >  Comment éviter les blocages dans Golang lors de l'utilisation de Goroutines et de canaux ?

Comment éviter les blocages dans Golang lors de l'utilisation de Goroutines et de canaux ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-27 06:48:29393parcourir

How to Prevent Deadlock in Golang When Using Goroutines and Channels?

Résoudre l'impasse des Goroutines

Lorsque vous travaillez avec des programmes Golang simultanés, vous pouvez rencontrer une erreur de blocage : "erreur fatale : toutes les goroutines sont endormies - impasse!". Cette erreur se produit lorsque plusieurs goroutines s'attendent les unes les autres pour effectuer une tâche, créant une situation de blocage.

Considérez le code suivant :

<code class="go">func producer(ch chan int, d time.Duration, num int) {
    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    ch := make(chan int)

    go producer(ch, 100*time.Millisecond, 2)
    go producer(ch, 200*time.Millisecond, 5)

    for {
        fmt.Println(<-ch)    
    }

    close(ch)
}</code>

Ce code crée deux goroutines productrices qui envoient des valeurs. sur le même canal. La goroutine principale reçoit en permanence des valeurs du canal dans une boucle sans fin.

Le problème se pose parce que les producteurs sont « de courte durée » et arrêtent d'envoyer des valeurs après un laps de temps fini, mais la goroutine principale continue de recevoir des valeurs. sans fin. Cela crée une impasse puisque le canal n'est jamais fermé pour signaler qu'aucune valeur ne sera envoyée.

Pour sortir de cette impasse, il faut s'assurer que le canal soit fermé lorsque tous les producteurs ont terminé leurs tâches. Le moyen efficace d'y parvenir est d'utiliser une primitive de synchronisation comme un sync.WaitGroup.

Voici une version modifiée du code :

<code class="go">func producer(ch chan int, d time.Duration, num int, wg *sync.WaitGroup) {
    defer wg.Done()

    for i := 0; i < num; i++ {
        ch <- i
        time.Sleep(d)
    }
}

func main() {
    wg := &sync.WaitGroup{}
    ch := make(chan int)

    wg.Add(1)
    go producer(ch, 100*time.Millisecond, 2, wg)
    wg.Add(1)
    go producer(ch, 200*time.Millisecond, 5, wg)

    go func() {
        wg.Wait()
        close(ch)
    }()

    for v := range ch {
        fmt.Println(v)
    }
}</code>

Dans ce code, nous passons une synchronisation. WaitGroup à chaque goroutine de producteur. Chaque producteur incrémente le groupe d'attente avant de démarrer et le décrémente à la fin. La goroutine principale attend la fin de tous les producteurs utilisant wg.Wait(). Une fois que tous les producteurs ont terminé, la goroutine principale ferme le canal.

Cette solution garantit que le canal n'est fermé qu'une fois que tous les producteurs ont terminé leur travail, évitant ainsi une situation de blocage.

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