Maison >développement back-end >Golang >Comment corriger les erreurs de blocage dans les canaux Go lors de l'utilisation de sync.WaitGroup ?

Comment corriger les erreurs de blocage dans les canaux Go lors de l'utilisation de sync.WaitGroup ?

Patricia Arquette
Patricia Arquetteoriginal
2024-10-29 02:36:02477parcourir

How to Fix Deadlock Errors in Go Channels When Using sync.WaitGroup?

Comprendre les erreurs de blocage dans les canaux Go

Dans cet article, nous analyserons les causes derrière le « blocage ! » erreur résultant d'une situation de blocage impliquant les canaux Go dans l'extrait de code suivant :

package main

import (
    "fmt"
    "sync"
)

func push(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    c := make(chan int)

    go push(c, wg)
    go pull(c, wg)

    wg.Wait()
}

Lors de l'exécution de ce code, nous rencontrons l'erreur suivante :

throw: all goroutines are asleep - deadlock!

Comprendre le blocage

Le blocage se produit parce que les structures, comme le sync.WaitGroup dans ce code, sont transmises par valeur et non par référence. Cela signifie que lorsque nous transmettons le WaitGroup à nos fonctions (push et pull), nous transmettons en fait une copie du WaitGroup au lieu de l'objet d'origine.

En conséquence, chaque fonction travaille sur sa propre copie. du WaitGroup, et lorsqu'ils appellent wg.Done(), ils décrémentent leurs propres copies. Cela ne met pas à jour le WaitGroup d'origine, ce qu'attend notre goroutine principale, conduisant ainsi à une impasse.

Résoudre l'impasse

Pour résoudre ce problème, nous devons passer le pointeur au WaitGroup au lieu de la valeur. Cela garantira que les fonctions push et pull fonctionnent sur la même instance de WaitGroup et que leurs appels à wg.Done() affecteront l'objet d'origine.

Voici une version corrigée du code :

package main

import (
    "fmt"
    "sync"
)

func push(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        c <- i
    }
    wg.Done()
}

func pull(c chan int, wg *sync.WaitGroup) {
    for i := 0; i < 5; i++ {
        result, ok := <-c
        fmt.Println(result, ok)
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    wg.Add(2)
    c := make(chan int)

    go push(c, &wg)
    go pull(c, &wg)

    wg.Wait()
}

En effectuant cette modification, nous transmettons désormais le pointeur vers le WaitGroup à nos fonctions, garantissant que les deux travaillent sur le même objet et mettent correctement à jour son état. Cela élimine la situation de blocage et permet à notre programme de s'exécuter sans aucune erreur.

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