Maison  >  Article  >  développement back-end  >  Demandez à Go d'exécuter toutes les goroutines avant de continuer

Demandez à Go d'exécuter toutes les goroutines avant de continuer

PHPz
PHPzavant
2024-02-11 17:20:17872parcourir

在继续之前要求 Go 运行所有 goroutine

Lors de la programmation simultanée, nous rencontrons souvent des situations où nous devons attendre que toutes les goroutines soient terminées avant de poursuivre l'exécution. En langage Go, nous pouvons atteindre cet objectif en utilisant WaitGroup. WaitGroup est un sémaphore de comptage qui peut être utilisé pour attendre la fin d'un groupe de goroutines. Avant de continuer, nous devons appeler la méthode Wait de WaitGroup pour nous assurer que toutes les goroutines ont terminé leurs tâches. Dans cet article, nous présenterons comment utiliser correctement WaitGroup pour gérer l'ordre d'exécution des goroutines.

Contenu de la question

J'ai besoin du planificateur Golang pour exécuter toutes les goroutines avant de continuer, runtime.gosched() ne peut pas le résoudre.

Le problème est que la routine go s'exécute si vite que le "select" dans start() s'exécute après le "select" dans stopstream() puis "case <-chanstopstream:" le destinataire n'est pas prêt pour l'expéditeur "case retchan <-true :". Il s'avère que lorsque cela se produit, le résultat est le même comportement que lorsque stopstream() se bloque

Exécutez ce code https://go.dev/play/p/dq85xqju2q_z Plusieurs fois, vous verrez ces deux réponses Réponse attendue lorsqu'il n'est pas suspendu :

2009/11/10 23:00:00 start
2009/11/10 23:00:00 receive chan
2009/11/10 23:00:03 end

Réponse attendue en cas de suspension, mais pas si rapide en cas de suspension :

2009/11/10 23:00:00 start
2009/11/10 23:00:00 default
2009/11/10 23:00:01 timer
2009/11/10 23:00:04 end

Code

package main

import (
    "log"
    "runtime"
    "sync"
    "time"
)

var wg sync.WaitGroup

func main() {
    wg.Add(1)
    //run multiples routines on a huge system
    go start()
    wg.Wait()
}
func start() {
    log.Println("Start")
    chanStopStream := make(chan bool)
    go stopStream(chanStopStream)
    select {
    case <-chanStopStream:
        log.Println("receive chan")
    case <-time.After(time.Second): //if stopStream hangs do not wait more than 1 second
        log.Println("TIMER")
        //call some crash alert
    }
    time.Sleep(3 * time.Second)
    log.Println("end")
    wg.Done()
}

func stopStream(retChan chan bool) {
    //do some work that can be faster then caller or not
    runtime.Gosched()
    //time.Sleep(time.Microsecond) //better solution then runtime.Gosched()
    //time.Sleep(2 * time.Second) //simulate when this routine hangs more than 1 second
    select {
    case retChan <- true:
    default: //select/default is used because if the caller times out this routine will hangs forever
        log.Println("default")
    }
}

Solution de contournement

Il n'y a aucun moyen d'exécuter toutes les autres goroutines avant de continuer l'exécution de la goroutine actuelle.

Correction du problème en s'assurant que la goroutine ne se bloque pas stopstream :

Option 1 : Remplacez chanstopstream par canal tamponné chanstopstream 更改为缓冲通道。这确保了 stopstream. Cela garantit que

peut envoyer des valeurs sans blocage.

func start() {
    log.println("start")
    chanstopstream := make(chan bool, 1) // <--- buffered channel
    go stopstream(chanstopstream)
    ...
}

func stopstream(retchan chan bool) {
    ...
    // always send. no select/default needed.
    retchan <- true
}
https://www.php.cn/link/56e48d306028f2a6c2ebf677f7e8f800

Option 2

 : Fermez le canal au lieu d'envoyer la valeur. Les chaînes peuvent toujours être fermées par l'expéditeur. Reçoit une valeur zéro sur un canal fermé qui renvoie le type de valeur du canal.

func start() {
    log.Println("Start")
    chanStopStream := make(chan bool) // buffered channel not required
    go stopStream(chanStopStream)
    ...

func stopStream(retChan chan bool) {
    ...
    close(retChan)
}
https://www.php.cn/link/a1aa0c486fb1a7ddd47003884e1fc67f

🎜

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer