Maison  >  Article  >  développement back-end  >  Comment arrêter gracieusement une routine Go : un guide pour éviter les blocages et les processus qui ne répondent pas ?

Comment arrêter gracieusement une routine Go : un guide pour éviter les blocages et les processus qui ne répondent pas ?

Linda Hamilton
Linda Hamiltonoriginal
2024-10-28 14:11:02535parcourir

 How to Gracefully Stop a Go Routine: A Guide to Avoiding Deadlocks and Unresponsive Processes?

Comment arrêter gracieusement une routine Go

Dans Go, les goroutines offrent une concurrence légère, mais il peut être difficile de les terminer gracieusement. Cette question répond à la nécessité d'envoyer un signal à une goroutine pour arrêter son exécution.

Le code fourni démontre une tentative d'arrêt d'une goroutine en définissant un indicateur booléen (trop tard) sur vrai. Cependant, cette approche est problématique car la lecture depuis un canal bloque la goroutine.

Solution 1 : Utiliser un canal supplémentaire

La solution implique d'utiliser un deuxième canal (trop tard) pour communiquer le signal d'arrêt. Ce canal reste ouvert même lorsque la goroutine ne le lit pas activement.

<code class="go">func main() {
    tooLate := make(chan struct{}) // Unbuffered channel for stop signal
    proCh := make(chan string)

    go func() {
        for {
            fmt.Println("working")
            time.Sleep(1 * time.Second)
            select {
            case <-tooLate:
                fmt.Println("stopped")
                return
            case proCh <- "processed": // Non-blocking send
            default: // Allows the goroutine to continue without blocking
            }
            fmt.Println("done here")
        }
    }()

    select {
    case proc := <-proCh:
        fmt.Println(proc)
    case <-time.After(1 * time.Second):
        fmt.Println("too late")
        close(tooLate) // Signal to goroutine to stop
    }

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}</code>

Dans cette solution, lorsque le délai expire, le canal trop tard est fermé, ce qui amène la goroutine à quitter son instruction de sélection de blocage et retour.

Solution 2 : Utilisation de sync.Cond

Vous pouvez également utiliser le type sync.Cond pour implémenter un mécanisme de signalisation plus sophistiqué. Voici un exemple :

<code class="go">func main() {
    var stopped bool
    cond := sync.NewCond(new(sync.Mutex))

    go func() {
        for {
            cond.L.Lock()
            defer cond.L.Unlock()

            if stopped {
                fmt.Println("stopped")
                return
            }
            fmt.Println("working")
            cond.Wait() // Wait for the signal to stop
        }
    }()

    time.Sleep(1 * time.Second)
    cond.Signal() // Send the stop signal

    time.Sleep(4 * time.Second)
    fmt.Println("finish\n")
}</code>

Avec cette approche, la goroutine attend la méthode cond.Wait() jusqu'à ce qu'elle reçoive un signal de cond.Signal().

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