Maison >développement back-end >Golang >Comment résoudre les blocages dans Go lorsque tous les Goroutines sont endormis ?

Comment résoudre les blocages dans Go lorsque tous les Goroutines sont endormis ?

Susan Sarandon
Susan Sarandonoriginal
2024-12-24 10:43:171034parcourir

How to Resolve Deadlocks in Go When All Goroutines Are Asleep?

Impasse dans Go : "Tous les goroutines sont endormis"

Lorsque vous travaillez avec des goroutines, il est crucial de gérer efficacement les opérations des canaux pour éviter les blocages. Cela se produit lorsque toutes les goroutines sont bloquées indéfiniment, conduisant à une situation de blocage.

Comprendre le code

Examinons le code fourni :

package main

import (
    "fmt"
    "sync"
    "time"
)

type Item struct {
    name string
}

type Truck struct {
    Cargo []Item
    name  string
}

func UnloadTrucks(c chan Truck) {
    for t := range c {
        fmt.Printf("%s has %d items in cargo: %s\n", t.name, len(t.Cargo), t.Cargo[0].name)
    }
}

func main() {
    trucks := make([]Truck, 2)
    ch := make(chan Truck)

    for i, _ := range trucks {
        trucks[i].name = fmt.Sprintf("Truck %d", i+1)
        fmt.Printf("Building %s\n", trucks[i].name)
    }

    for t := range trucks {
        go func(tr Truck) {
            itm := Item{}
            itm.name = "Groceries"

            fmt.Printf("Loading %s\n", tr.name)
            tr.Cargo = append(tr.Cargo, itm)
            ch <- tr
        }(trucks[t])
    }

    time.Sleep(50 * time.Millisecond)
    fmt.Println("Unloading Trucks")
    UnloadTrucks(ch)

    fmt.Println("Done")
}

Ce code crée un canal ch de type Truck et lance deux goroutines pour simuler le chargement de camions de produits d'épicerie et leur envoi vers le canal. Il appelle ensuite UnloadTrucks pour récupérer et imprimer le contenu des camions.

Cause du blocage

Le problème réside dans l'absence de mécanisme pour fermer le canal ch. Lorsque tous les goroutines ont envoyé leurs camions vers le canal, il n'y a aucun signal pour terminer la boucle dans UnloadTrucks. Cela signifie que ch continue d'écouter les valeurs qui n'arrivent jamais, ce qui entraîne un blocage.

Solution

Pour résoudre le blocage, nous devons fermer explicitement le canal ch lorsque les goroutines de chargement sont terminées. Nous pouvons utiliser un sync.WaitGroup pour compter les goroutines en cours d'exécution et fermer le canal lorsque tous ont terminé :

var wg sync.WaitGroup

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

Cette modification garantit que UnloadTrucks se terminera une fois que toutes les goroutines auront fini de charger les camions. La fonction Wait se bloque jusqu'à ce que le compteur WaitGroup atteigne zéro, indiquant que toutes les goroutines ont terminé leur travail. La fermeture du canal signale à UnloadTrucks qu'il n'y a plus de camions à recevoir, lui permettant ainsi de sortir gracieusement de la boucle.

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