Table des matières
Contenu de la question
La solution
Meilleure façon : utilisez des nilcanaux disponibles pour la sélection
Maison développement back-end Golang Quelle est la meilleure pratique dans Golang pour suivre l'état d'achèvement de deux Goroutines au sein d'une troisième Goroutine ?

Quelle est la meilleure pratique dans Golang pour suivre l'état d'achèvement de deux Goroutines au sein d'une troisième Goroutine ?

Feb 11, 2024 pm 02:54 PM
overflow

Golang 中跟踪第三个 Goroutine 中两个 Goroutine 的完成状态的最佳实践是什么?

Quelle est la meilleure pratique dans Golang pour suivre l'état d'achèvement de deux Goroutines dans une troisième Goroutine ? Dans Golang, pour suivre l'état d'achèvement de deux Goroutines et traiter leurs résultats dans un troisième Goroutine, la meilleure pratique consiste à utiliser WaitGroup du package de synchronisation. WaitGroup nous permet d'attendre dans le Goroutine principal la fin des autres Goroutines. Tout d’abord, nous devons créer un objet WaitGroup et appeler la méthode Add dans le Goroutine principal pour définir le nombre de Goroutines en attente. Ensuite, la méthode Done est appelée à la fin de chaque Goroutine pour signaler l'achèvement de cette Goroutine. Enfin, la méthode Wait est appelée dans le troisième Goroutine pour attendre que tous les Goroutines se terminent. De cette façon, nous pouvons suivre et traiter en toute sécurité les résultats des deux Goroutines. Il s'agit de la meilleure pratique de Golang pour suivre l'état d'achèvement de plusieurs Goroutines.

Contenu de la question

J'ai trois goroutines exécutées simultanément. Deux d'entre eux effectuent un traitement et envoient leurs résultats au canal de résultats. La troisième goroutine « compte » les résultats en lisant les canaux de résultats. Je pourrais utiliser un groupe d'attente pour attendre la fin des deux goroutines de calcul, puis parcourir les canaux de résultats pour comptabiliser les résultats, mais cela ne s'adapte pas et m'oblige à créer un canal de résultats mis en mémoire tampon avec une taille de tampon énorme, ce qui est inacceptable. dans le code de production.

Je souhaite compter les résultats pendant le traitement, mais je ne veux pas quitter le programme avant que tout le comptage ne soit terminé. Quelles sont les bonnes pratiques pour y parvenir dans Go ?

C'est ma méthode actuelle et elle fonctionne très bien. Je me demande s'il existe une meilleure solution car cela semble un peu maladroit ?

package main

import (
    "fmt"
    "sync"
)

type T struct{}

func main() {
    var widgetInventory int = 1000
    transactions := make(chan int, 100)
    salesDone := make(chan T)
    purchasesDone := make(chan T)
    var wg sync.WaitGroup
    fmt.Println("Starting inventory count = ", widgetInventory)

    go makeSales(transactions, salesDone)
    go newPurchases(transactions, purchasesDone)

    wg.Add(1)

    go func() {
        salesAreDone := false
        purchasesAreDone := false

        for {
            select {
            case transaction := <-transactions:
                widgetInventory += transaction
            case <-salesDone:
                salesAreDone = true
            case <-purchasesDone:
                purchasesAreDone = true
            default:
                if salesAreDone && purchasesAreDone {
                    wg.Done()
                    return
                }
            }
        }
    }()

    wg.Wait()
    fmt.Println("Ending inventory count = ", widgetInventory)
}

func makeSales(transactions chan int, salesDone chan T) {
    for i := 0; i < 3000; i++ {
        transactions <- -100
    }

    salesDone <- struct{}{}
}

func newPurchases(transactions chan int, purchasesDone chan T) {
    for i := 0; i < 3000; i++ {
        transactions <- 100
    }

    purchasesDone <- struct{}{}
}
Copier après la connexion

La solution

ne correspond à aucune définition raisonnablebien. Vous avez une boucle for populaire ici :

for {
            select {
            case transaction := <-transactions:
                widgetInventory += transaction
            case <-salesDone:
                salesAreDone = true
            case <-purchasesDone:
                purchasesAreDone = true
            default:
                if salesAreDone && purchasesAreDone {
                    wg.Done()
                    return
                }
            }
        }
Copier après la connexion

Tant qu'il n'y a aucun canal à partir duquel lire, le cas default sera exécuté. Cela arrive souvent en raison du fonctionnement des chaînes.

Cette version légèrement ajustée du code illustre la "chaleur" de cette boucle. Les résultats exacts varient et peuvent être assez élevés.

Default case ran 27305 times
Copier après la connexion

Vous ne voulez pas le cas selecting 来自通道时,您不希望出现 default lorsque vous sélectionnez un canal, à moins que cette valeur par défaut bloque également quelque chose dedans. Sinon, vous obtiendrez un cycle thermique comme celui-ci.

Meilleure façon : utilisez des nilcanaux disponibles pour la sélection

Généralement, dans une sélection, vous souhaitez identifier un canal fermé et définir la variable de canal sur nilselect 永远不会成功地从 nil

 ; select ne réussira jamais à lire le canal

, donc cela "désactive" effectivement le choix. Considérez cette version modifiée

du

code : salesDonepurchasesDone 都被“发出信号”,我们 close(transactions)。一旦我们耗尽 transactions 并且它被关闭,我们将 transactions 设置为 nil。我们在 transactions 不为 nil 时循环,在这段代码中,意味着所有通道都是 nil

go func(transactions chan int, salesDone <-chan T, purchasesDone <-chan T) {
        defer wg.Done()
        for transactions != nil {
            select {
            case transaction, ok := <-transactions:
                if ok {
                    widgetInventory += transaction
                } else {
                    transactions = nil
                }
            case <-salesDone:
                salesDone = nil
                if purchasesDone == nil {
                    close(transactions)
                }
            case <-purchasesDone:
                purchasesDone = nil
                if salesDone == nil {
                    close(transactions)
                }

            }
        }
    }(transactions, salesDone, purchasesDone)
Copier après la connexion

Avec ces ajustements au consommateur, nous n'avons plus de boucles chaudes ; nous bloquons toujours jusqu'à ce que les données soient lues depuis le canal. Une fois que salesDone et purchasesDone ont été "signalés", nous fermons (transactions). Une fois que nous avons épuisé les transactions

et que main 共享范围。否则,将 transactions 设置为 nil 将写入一个在 goroutine 之间共享的变量。然而在这种情况下,无论如何,这并不重要,因为我们“知道”我们是最后一个从 transactions est fermée, nous définissons transactions à zéro. Nous bouclons lorsque transactions n'est pas nul, ce qui dans ce code signifie que tous les canaux sont

.

Point subtil mais important : je passe un canal à cette fonction afin que sa référence ne partage pas la portée avec main. Sinon, définir transactions sur

écrira dans une variable partagée entre les goroutines. Dans ce cas, cependant, cela n'a pas d'importance, car nous "savons" que nous sommes les derniers à lire les transactions. transactions 的生产。然后你想排空 transactions。一旦通道关闭并排空,main

Option plus simple : plusieurs groupes d'attente

select 来执行此操作。而 selectSi vous réfléchissez à ce que vous faites ici, vous devez attendre que les deux producteurs aient fini de s'associer

avant de savoir que la somme est terminée.

Vous n'avez pas besoin 🎜 d'avoir un cas pour chaque "travailleur", ce qui est sans doute assez inélégant ; vous devez coder en dur plusieurs travailleurs et gérer le canal "d'achèvement" individuellement. 🎜 🎜Ce que vous devez faire est :🎜
  • 除了为生产者使用一个 var resultswgsync.WaitGroup 之外,还为消费者添加一个。
  • 生产者 defer wg.Done()
  • 消费者 defer resultswg.Done() 在遍历 transactions 之前:
    go func() {
        defer resultswg.Done()
        for transaction := range transactions {
            widgetInventory += transaction
        }
    }()
    Copier après la connexion
  • main 处理等待生产者、关闭事务以结束范围,然后等待消费者:
    wg.Wait()
    close(transactions)
    resultswg.Wait()
    Copier après la connexion

以这种方式编码,最终会变得简短而甜蜜

package main

import (
    "fmt"
    "sync"
)

func main() {
    var widgetInventory int = 1000
    transactions := make(chan int, 100)

    var wg, resultswg sync.WaitGroup
    fmt.Println("Starting inventory count = ", widgetInventory)
    wg.Add(2)

    go makeSales(transactions, &wg)
    go newPurchases(transactions, &wg)
    resultswg.Add(1)
    go func() {
        defer resultswg.Done()
        for transaction := range transactions {
            widgetInventory += transaction
        }
    }()

    wg.Wait()
    close(transactions)
    resultswg.Wait()
    fmt.Println("Ending inventory count = ", widgetInventory)
}

func makeSales(transactions chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 3000; i++ {
        transactions <- -100
    }

}

func newPurchases(transactions chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    for i := 0; i < 3000; i++ {
        transactions <- 100
    }

}
Copier après la connexion

您可以在这里看到,在此模式中可以有任意数量的生产者;您只需为每个生产者添加 wg.Add(1) 即可。

当我不知道每个工作人员会返回多少结果时,我一直使用这种模式来并行化工作。我发现它很容易理解,并且比尝试 select 多个通道简单得多。事实上,我什至想说,如果您发现自己从多个渠道进行 selecting,您应该退后一步,确保它对您来说确实有意义。我使用 select 的频率远远低于使用等待组的频率。

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 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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
2 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Repo: Comment relancer ses coéquipiers
1 Il y a quelques mois By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
4 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Le prix du Bitcoin depuis sa naissance 2009-2025 Le résumé le plus complet des prix historiques du BTC Le prix du Bitcoin depuis sa naissance 2009-2025 Le résumé le plus complet des prix historiques du BTC Jan 15, 2025 pm 08:11 PM

Depuis sa création en 2009, Bitcoin est devenu un leader dans le monde des cryptomonnaies et son prix a connu d’énormes fluctuations. Pour fournir un aperçu historique complet, cet article compile les données sur les prix du Bitcoin de 2009 à 2025, couvrant les principaux événements du marché, les changements de sentiment du marché et les facteurs importants influençant les mouvements de prix.

Que faire si l'heure dans le coin inférieur droit de Windows 11 est révolue_Que faire si l'heure dans le coin inférieur droit de Windows 11 est révolue Que faire si l'heure dans le coin inférieur droit de Windows 11 est révolue_Que faire si l'heure dans le coin inférieur droit de Windows 11 est révolue May 06, 2024 pm 01:20 PM

1. Tout d’abord, faites un clic droit sur l’espace vide de la barre des tâches en bas de Windows 11 et sélectionnez [Paramètres de la barre des tâches]. 2. Recherchez [taskbarcorneroverflow] à droite dans les paramètres de la barre des tâches. 3. Recherchez ensuite [horloge] ou [Horloge] au-dessus et sélectionnez pour l'allumer. Méthode 2 : 1. Appuyez sur le raccourci clavier [win+r] pour appeler run, entrez [regedit] et appuyez sur Entrée pour confirmer. 2. Ouvrez l'éditeur de registre, recherchez-y [HKEY_CURRENT_USERControlPanel] et supprimez-le. 3. Après la suppression, redémarrez l'ordinateur et vous serez invité à effectuer la configuration. Lorsque vous reviendrez au système, l'heure s'affichera.

Existe-t-il des forums communautaires ou des groupes de discussion sur les fonctions Java où je peux poser des questions et en discuter ? Existe-t-il des forums communautaires ou des groupes de discussion sur les fonctions Java où je peux poser des questions et en discuter ? Apr 28, 2024 pm 02:12 PM

Réponse : Les forums communautaires et groupes de discussion suivants sont disponibles pour les questions de programmation fonctionnelle Java : StackOverflow : le plus grand site Web de questions et réponses sur la programmation au monde avec une communauté d'experts en programmation fonctionnelle Java. JavaFunctionalProgramming : un forum communautaire axé sur la programmation fonctionnelle Java, proposant des discussions sur les concepts, les fonctionnalités du langage et les meilleures pratiques. Redditr/FunctionalJava : un sous-reddit axé sur la programmation Java fonctionnelle, en se concentrant sur les outils, les bibliothèques et les technologies. Discord : JavaFunctional Programming : service Discord qui propose des discussions, un partage de code et une collaboration en temps réel

Comment utiliser le code d'autres personnes en python Comment utiliser le code d'autres personnes en python May 05, 2024 pm 07:54 PM

Comment utiliser le code Python d’autres personnes ? Rechercher des référentiels de code : recherchez le code dont vous avez besoin sur des plateformes telles que PyPI et GitHub. Code d'installation : utilisez pip ou clonez le référentiel GitHub pour l'installer. Importer des modules : utilisez l'instruction import dans votre script pour importer les modules installés. Travailler avec du code : accédez aux fonctions et aux classes dans les modules. (Facultatif) Adaptez le code : modifiez le code si nécessaire pour l'adapter à votre projet.

Que dois-je faire si l'heure sur mon ordinateur Win11 est toujours fausse ? Comment régler la mauvaise heure sur un ordinateur Windows 11 Que dois-je faire si l'heure sur mon ordinateur Win11 est toujours fausse ? Comment régler la mauvaise heure sur un ordinateur Windows 11 May 03, 2024 pm 09:20 PM

Que dois-je faire si l'heure sur mon ordinateur Win11 est toujours fausse ? Nous définissons tous l'heure ou le calendrier lorsque nous utilisons le système Win11, mais de nombreux utilisateurs demandent que l'heure de l'ordinateur soit toujours erronée, alors que se passe-t-il ? Les utilisateurs peuvent cliquer directement sur la barre des tâches ci-dessous, puis rechercher taskbarcorneroverflow pour la configurer. Laissez ce site présenter en détail aux utilisateurs comment ajuster l'erreur de temps sur les ordinateurs Win11. Comment régler l'erreur d'heure de l'ordinateur dans Windows 11. Méthode 1 : 1. Nous faisons d'abord un clic droit sur l'espace vide de la barre des tâches ci-dessous et sélectionnons Paramètres de la barre des tâches. Méthode 2 : 1. Appuyez sur le raccourci clavier win+r pour appeler run, entrez regedit et appuyez sur Entrée pour confirmer.

Types d'exceptions courants et leurs mesures de réparation dans le développement de fonctions Java Types d'exceptions courants et leurs mesures de réparation dans le développement de fonctions Java May 03, 2024 pm 02:09 PM

Types d'exceptions courants et leurs mesures de réparation dans le développement de fonctions Java Lors du développement de fonctions Java, diverses exceptions peuvent survenir, affectant l'exécution correcte de la fonction. Voici les types d'exceptions courants et leurs mesures de réparation : 1. NullPointerException Description : levée lors de l'accès à un objet qui n'a pas été initialisé. Correctif : assurez-vous de vérifier que l'objet n'est pas nul avant de l'utiliser. Exemple de code : try{Stringname=null;System.out.println(name.length());}catch(NullPointerExceptione){

Que signifie le débordement en CSS Que signifie le débordement en CSS Apr 28, 2024 pm 03:15 PM

overflow est une propriété CSS utilisée pour contrôler le mode d'affichage du contenu de l'élément lorsqu'il dépasse le conteneur. Les valeurs disponibles incluent : visible : le contenu est visible, le conteneur de débordement est masqué : le contenu du débordement est coupé scroll : le la barre de défilement s'affiche pour visualiser le contenu de débordement auto : le navigateur détermine automatiquement s'il faut afficher la barre de défilement hériter : hérite de l'attribut de débordement de l'élément parent

Personne ne s'occupe des comptes aléatoires de Douyin ? Puis-je faire appel une deuxième fois ? Personne ne s'occupe des comptes aléatoires de Douyin ? Puis-je faire appel une deuxième fois ? May 03, 2024 am 09:37 AM

En tant que plate-forme de vidéos courtes de renommée mondiale, Douyin dispose d'une énorme base d'utilisateurs et de créateurs de contenu. Cependant, comme les règles de la plateforme sont constamment mises à jour et améliorées, certains utilisateurs peuvent se heurter à des interdictions de compte. Cela a soulevé des questions publiques sur la transparence et l’équité de la gestion de la plateforme. Cet article abordera la question des interdictions de compte Douyin et si les utilisateurs ont des moyens de faire appel après l'interdiction de leurs comptes. Il peut y avoir de nombreuses raisons d'être banni de la plateforme Douyin, y compris, mais sans s'y limiter, le contenu illégal, la violation des réglementations de la plateforme, la violation des droits d'autrui, etc. Afin de maintenir l'ordre de la plateforme et les intérêts des utilisateurs, Douyin a mis en place une série de règles et de mécanismes de contrôle. Lorsque certains utilisateurs enfreignent les règles, leurs comptes peuvent être bannis. Cependant, certains utilisateurs peuvent s'interroger ou être insatisfaits des raisons de l'interdiction.

See all articles