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

Comment éviter les impasses dans Go Goroutines lorsque les producteurs sont de courte durée ?

Linda Hamilton
Libérer: 2024-10-25 07:09:02
original
792 Les gens l'ont consulté

How to Avoid Deadlock in Go Goroutines When Producers Are Short-Lived?

Résoudre les blocages dans les goroutines Go

Dans la programmation simultanée, un blocage se produit lorsque plusieurs goroutines s'attendent indéfiniment pour terminer les opérations, interrompant ainsi le processus. programme. Cet article traite d'un blocage spécifique rencontré dans la simultanéité Go, comme décrit dans la question d'origine :

<code class="go">package main

import (
    "fmt"
    "time"
)

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>
Copier après la connexion

Ce code déclenche une erreur de blocage en raison des facteurs suivants :

  • Les producteurs , qui envoient des valeurs au canal, sont de courte durée et finissent par cesser de produire des données.
  • La boucle for sans fin dans la fonction principale reçoit en continu des valeurs du canal sans condition de terminaison.
  • Le Le canal est fermé après la boucle sans fin, ce qui fait qu'aucune autre valeur n'est disponible pour la réception.

Solution : résiliation coordonnée

Pour éviter une impasse, les producteurs doivent être coordonné pour signaler l'achèvement, et la chaîne doit être fermée par le dernier producteur. Voici une solution efficace utilisant un sync.WaitGroup pour la coordination :

<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>
Copier après la connexion

Dans cette solution :

  • On incrémente le WaitGroup pour chaque producteur.
  • Chaque producteur décrémente le WaitGroup une fois terminé via une instruction defer.
  • Une goroutine attend que le WaitGroup atteigne zéro (ce qui signifie que tous les producteurs ont terminé) et ferme le canal.
  • La boucle principale utilise une plage for construire pour parcourir les valeurs envoyées sur le canal avant sa fermeture.

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!