Rumah > Artikel > pembangunan bahagian belakang > Bagaimanakah kami menjamin bahawa konteks yang dibatalkan akan menyebabkan goroutine ditamatkan?
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.
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
ctx.done()
juga mempunyai nilai untuk diterima. Soalan:
select
Mengikut perjalanan pergi, select
不会继续选择 <- intchan
案例?如果 <- ctx.done()
案例在 for 循环的每次迭代中都准备就绪,我们如何知道 <- ctx.done()
Bagaimana untuk memastikan bahawa <- intchan
? Jika kes <- ctx.done()
sedia pada setiap lelaran gelung for, bagaimana kita tahu bahawa <- ctx.done() Kes akhirnya akan dipilih?
func consumer(ctx context.context, intchan chan int) { for { select { case <-ctx.done(): return case i := <-intchan: foo(i) } } }
consumer
Saya cuba menggunakan fungsi consumer
和 producer
dalam program di bawah.
Dalam pelbagai larian program ini, goroutine dan producer
sentiasa kelihatan ditamatkan.
<-ctx.done()
Kenapa kita tidak berakhir dengan
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: } } }Penyelesaian
ctx.err()
Tiada jaminan. Cara paling mudah untuk menjamin penamatan ialah menggunakan
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() }
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!