Maison  >  Article  >  développement back-end  >  Comment pouvons-nous garantir que le contexte annulé entraînera la fin de la goroutine ?

Comment pouvons-nous garantir que le contexte annulé entraînera la fin de la goroutine ?

PHPz
PHPzavant
2024-02-08 23:54:23927parcourir

我们如何保证取消的上下文会导致 goroutine 终止?

L'éditeur PHP Zimo vous présentera comment s'assurer que l'annulation du contexte entraînera la fin de la goroutine. Lorsque nous utilisons goroutine, nous devons parfois l'annuler lorsqu'une certaine condition est remplie pour éviter des calculs inutiles et un gaspillage de ressources. Pour garantir que la goroutine se termine correctement, nous pouvons utiliser le mécanisme fourni par le package de contexte. Le package de contexte fournit un moyen de transmettre les requêtes entre les goroutines et d'annuler ces requêtes en cas de besoin. En utilisant le package de contexte de manière appropriée, nous pouvons garantir que la goroutine se termine correctement lorsque le contexte est annulé, évitant ainsi les fuites de ressources et autres problèmes potentiels. Ci-dessous, nous détaillerons comment utiliser le package contextuel pour atteindre cet objectif.

Contenu de la question

Supposons que ce qui suit se produise :

  • Nous avons la consumer fonction suivante, exécutée dans une goroutine.

  • Une autre goroutine est en ligne intchan 通道上毫无延迟地发送整数。换句话说,在 for 循环的每次迭代中,intchan toutes deux avec une valeur prête à recevoir.

  • La goroutine qui a démarré la consumer goroutine 的 goroutine 已取消传递到 consumer 的上下文。因此,ctx.done() goroutine a annulé le contexte transmis à

    . Par conséquent, le canal ctx.done() a également une valeur à recevoir.

Question :
  • Dans ce cas, les deux cas de l'instruction select sont prêts à être exécutés.
  • selectSelon le voyage de départ,
  • sélectionnera au hasard un cas puisque les deux sont prêts à fonctionner.
  • select 不会继续选择 <- intchan 案例?如果 <- c​​tx.done() 案例在 for 循环的每次迭代中都准备就绪,我们如何知道 <- c​​tx.done()Comment s'assurer que
  • ne continuera pas à choisir le cas <- intchan ? Si le cas <- c​​tx.done() est prêt à chaque itération de la boucle for, comment savons-nous que <- c​​tx.done() Les cas seront-ils éventuellement sélectionnés ?

func consumer(ctx context.context, intchan chan int) {
    for {
        select {
        case <-ctx.done():
            return
        case i := <-intchan:
            foo(i)
        }
    }
}
consumerJ'ai essayé d'utiliser la fonction consumerproducer dans le programme ci-dessous. Dans plusieurs exécutions de ce programme, les goroutines

et producteur semblent toujours se terminer.

<-ctx.done()Pourquoi ne pas se retrouver avec une

course où l'affaire n'est jamais exécutée ?
package main

import (
    "context"
    "fmt"
    "sync"
    "time"
)

func main() {

    ctx, cancelFunc := context.WithCancel(context.Background())

    var wg sync.WaitGroup
    wg.Add(2) // add 2, because we spawn 2 goroutines

    Producer(ctx, &wg)

    fmt.Println(time.Now())
    time.Sleep(time.Second * 5) // cancel the context after 5 seconds

    cancelFunc()
    fmt.Println("CANCELLED")

    wg.Wait() // wait till both producer and consumer goroutines terminate
    fmt.Println(time.Now())

}

func Producer(ctx context.Context, wg *sync.WaitGroup) {
    intChan := make(chan int)

    go Consumer(ctx, intChan, wg)

    go func() {
        defer wg.Done()
        for {
            select {
            case <-ctx.Done():
                return
            case intChan <- 1:
            }
        }
    }()

}

func Consumer(ctx context.Context, intChan chan int, wg *sync.WaitGroup) {
    defer wg.Done()

    for {
        select {
        case <-ctx.Done():
            return
        case _ = <-intChan:
        }
    }
}

Solution

ctx.err()Aucune garantie. Le moyen le plus simple de garantir la résiliation est d'utiliser

pour vérifier les erreurs en dehors de l'instruction select. Il est également courant de renvoyer des erreurs au code passant le contexte. J'écrirais la fonction consommateur comme ceci : 🎜
func Consumer(ctx context.Context, intChan chan int) error {
    for ctx.Err() == nil {
        select {
        case <-ctx.Done():
        case i := <-intChan:
            foo(i)
        }
    }
    return ctx.Err()
}

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