Maison  >  Article  >  développement back-end  >  Comment éviter les blocages lors de l'utilisation de sync.WaitGroup avec des fonctions externes dans Go ?

Comment éviter les blocages lors de l'utilisation de sync.WaitGroup avec des fonctions externes dans Go ?

Mary-Kate Olsen
Mary-Kate Olsenoriginal
2024-11-05 22:03:02877parcourir

How to Avoid Deadlocks When Using sync.WaitGroup with External Functions in Go?

Meilleures pratiques pour utiliser sync.WaitGroup avec des fonctions externes

Pour gérer la concurrence dans Go, il est crucial d'utiliser efficacement sync.WaitGroup. Cet article aborde un problème courant qui survient lors du passage d'un groupe d'attente comme argument à une fonction externe.

Problème :

Considérez le code suivant :

<code class="go">package main

import (
    "fmt"
    "sync"
)

func main() {
    ch := make(chan int)
    var wg sync.WaitGroup
    wg.Add(2)
    go Print(ch, wg) //
    go func(){

        for i := 1; i <= 11; i++ {
            ch <- i
        }

        close(ch)
        defer wg.Done()


    }()

    wg.Wait() //deadlock here
}

// Print prints all numbers sent on the channel.
// The function returns when the channel is closed.
func Print(ch <-chan int, wg sync.WaitGroup) {
    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }
    defer wg.Done()
}</code>

Dans ce code, un blocage se produit au niveau de la ligne spécifiée, obligeant le programme à imprimer uniquement de 1 à 10 au lieu d'atteindre 11. L'erreur provient du passage d'une copie de sync.WaitGroup à la méthode Print, ce qui gêne l'appel attendu à sa méthode Done.

Solution 1 :

Pour résoudre ce problème, passez plutôt un pointeur vers le groupe d'attente :

<code class="go">package main

import (
    "fmt"
    "sync"
)

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

    var wg sync.WaitGroup
    wg.Add(2)    

    go Print(ch, &wg)

    go func() {  
        for i := 1; i <= 11; i++ {
            ch <- i
        }
        close(ch)
        defer wg.Done()
    }()          

    wg.Wait() //deadlock here
}                

func Print(ch <-chan int, wg *sync.WaitGroup) {
    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }            
    defer wg.Done()
}</code>

Transmettre l'adresse de wg garantit que la méthode Print appelle la méthode Done sur le groupe d'attente qui est attendu dans la fonction principale.

Solution 2 : Méthode d'impression simplifiée

Alternativement, la méthode Print peut être simplifiée en supprimant l'argument WaitGroup, car elle ne nécessite la connaissance d'aucune opération d'attente :

<code class="go">package main

import (
    "fmt"
)

func main() {    
    ch := make(chan int)
    go func() {  
        for i := 1; i <= 11; i++ {
            ch <- i
        }
        close(ch)
    }()          

    for n := range ch { // reads from channel until it's closed
        fmt.Println(n)
    }            
}                </code>

Dans ce scénario, la goroutine principale reçoit directement le canal et imprime ses valeurs sans impliquer un groupe d'attente. Cette approche maintient la fonctionnalité souhaitée et élimine le besoin de gestion WaitGroup au sein de la méthode Print.

Conclusion :

Lors du passage de sync.WaitGroup comme argument à des fonctions externes, il est essentiel de s'assurer que la fonction reçoit la bonne référence au groupe d'attente attendu. Refactoriser la fonction pour gérer directement les groupes d'attente ou passer un pointeur vers le groupe d'attente peut efficacement éviter les erreurs de blocage et garantir un contrôle de concurrence approprié.

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