Bagaimanakah kami menjamin bahawa konteks yang dibatalkan akan menyebabkan goroutine ditamatkan?

PHPz
Lepaskan: 2024-02-08 23:54:23
ke hadapan
981 orang telah melayarinya

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

Editor PHP Zimo akan memperkenalkan kepada anda cara untuk memastikan bahawa pembatalan konteks akan menyebabkan goroutine ditamatkan. Apabila kita menggunakan goroutine, kadangkala kita perlu membatalkannya apabila syarat tertentu dipenuhi untuk mengelakkan pengiraan dan pembaziran sumber yang tidak perlu. Untuk memastikan bahawa goroutine ditamatkan dengan betul, kita boleh menggunakan mekanisme yang disediakan oleh pakej konteks. Pakej konteks menyediakan cara untuk menghantar permintaan antara goroutine dan membatalkan permintaan tersebut apabila diperlukan. Dengan menggunakan pakej konteks dengan sewajarnya, kami boleh memastikan bahawa goroutine ditamatkan dengan betul apabila konteks dibatalkan, dengan itu mengelakkan kebocoran sumber dan masalah lain yang berpotensi. Di bawah ini kami akan memperincikan cara menggunakan pakej konteks untuk mencapai matlamat ini.

Kandungan soalan

Andaikan perkara berikut berlaku:

  • Kami mempunyai fungsi consumer berikut, berjalan dalam goroutine.

  • Satu lagi goroutine dihidupkan intchan 通道上毫无延迟地发送整数。换句话说,在 for 循环的每次迭代中,intchan kedua-duanya dengan nilai sedia untuk diterima.

  • Groutine yang memulakan consumer goroutine 的 goroutine 已取消传递到 consumer 的上下文。因此,ctx.done() goroutine telah membatalkan konteks yang dihantar ke

    . Oleh itu, saluran ctx.done() juga mempunyai nilai untuk diterima.

Soalan:
  • Dalam kes ini, kedua-dua kes pernyataan pilih sedia untuk dijalankan.
  • selectMengikut perjalanan pergi,
  • akan memilih satu kes secara rawak kerana kedua-duanya sedia untuk dijalankan.
  • select 不会继续选择 <- intchan 案例?如果 <- c​​tx.done() 案例在 for 循环的每次迭代中都准备就绪,我们如何知道 <- c​​tx.done()Bagaimana untuk memastikan bahawa
  • tidak akan terus memilih kes <- intchan? Jika kes <- c​​tx.done() sedia pada setiap lelaran gelung for, bagaimana kita tahu bahawa <- c​​tx.done() Kes akhirnya akan dipilih?

func consumer(ctx context.context, intchan chan int) {
    for {
        select {
        case <-ctx.done():
            return
        case i := <-intchan:
            foo(i)
        }
    }
}
Salin selepas log masuk
consumerSaya cuba menggunakan fungsi consumerproducer dalam program di bawah. Dalam pelbagai larian program ini, goroutine

dan producer sentiasa kelihatan ditamatkan.

<-ctx.done()Kenapa kita tidak berakhir dengan

larian di mana kes itu tidak pernah dilaksanakan?

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:
        }
    }
}
Salin selepas log masuk

Penyelesaian

ctx.err()Tiada jaminan. Cara paling mudah untuk menjamin penamatan ialah menggunakan

untuk menyemak ralat di luar pernyataan pilih. Ia juga biasa untuk mengembalikan ralat kepada kod yang menghantar konteks. Saya akan menulis fungsi pengguna seperti ini: 🎜
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()
}
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimanakah kami menjamin bahawa konteks yang dibatalkan akan menyebabkan goroutine ditamatkan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan