Maison  >  Article  >  développement back-end  >  Comment éviter les impasses lors de la collecte des résultats des Goroutines ?

Comment éviter les impasses lors de la collecte des résultats des Goroutines ?

Patricia Arquette
Patricia Arquetteoriginal
2024-11-06 14:22:02650parcourir

How to Avoid Deadlocks When Gathering Results from Goroutines?

Utilisation de Goroutines pour le traitement des données

Dans Go, les goroutines sont des threads légers qui permettent l'exécution simultanée de tâches. Lorsque vous travaillez avec des goroutines, il est important de collecter correctement les résultats après le traitement pour éviter les blocages.

Énoncé du problème

Considérez l'extrait de code suivant :

sampleChan := make(chan sample)
var wg sync.WaitGroup

// Read from contents list
for i, line := range contents {
    wg.Add(1)
    // Process each item with a goroutine and send output to sampleChan
    go newSample(line, *replicatePtr, *timePtr, sampleChan, &wg)
}
wg.Wait()

// Read from sampleChan and put into a slice
var sampleList []sample
for s := range sampleChan {
    sampleList = append(sampleList, s)
}
close(sampleChan)

Ce code tente de traiter les éléments d'une liste à l'aide de goroutines et de rassembler les résultats dans une tranche. Cependant, il rencontre une erreur de blocage car le canal est fermé avant que les résultats ne soient collectés.

Solution

Pour résoudre ce problème, nous pouvons après tout fermer le canal de manière asynchrone les ouvriers ont fini le traitement. Voici le code corrigé :

for i, line := range contents {
    wg.Add(1)
    // Process each item with a goroutine and send output to sampleChan
    go newSample(line, *replicatePtr, *timePtr, sampleChan, &wg)
}

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

for s := range sampleChan {
  ..
}

Ce code démarre des goroutines qui traitent les éléments et envoient les résultats à sampleChan. Parallèlement, il démarre également une autre goroutine qui attend que tous les travailleurs aient terminé, puis ferme le canal. Cela garantit que tous les résultats sont collectés avant la fermeture du canal.

Solution alternative

Pour une meilleure lisibilité et testabilité du code, il est recommandé d'utiliser une fonction newSample synchrone et de gérer la concurrence dans la goroutine principale.

for i, line := range contents {
    wg.Add(1)
    go func(line string) {
        defer wg.Done()
        sampleChan <- newSample(line, *replicatePtr, *timePtr)
    }(line)
}

Cette approche maintient les primitives de concurrence localisées, simplifiant la maintenance du code et réduisant le risque d'erreurs.

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