我們如何保證取消的上下文會導致 goroutine 終止?

PHPz
發布: 2024-02-08 23:54:23
轉載
874 人瀏覽過

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

php小編子墨將為大家介紹如何保證取消上下文會導致goroutine終止的方法。當我們在使用goroutine時,有時需要在某個條件滿足時取消它,以避免不必要的計算和資源浪費。為了確保goroutine能夠正確終止,我們可以使用context套件提供的機制。 context包提供了一種在goroutine之間傳遞請求的方法,並且可以在需要時取消這些請求。透過合理地使用context包,我們可以確保goroutine在取消上下文時能夠正確地終止,從而避免資源洩漏和其他潛在的問題。下面我們將詳細介紹如何使用context套件來實現這一目標。

問題內容

假設發生下列情況:

  • 我們有下面的consumer函數,在 goroutine 中運行。

  • 另一個 goroutine 正在intchan通道上毫無延遲地發送整數。換句話說,在 for 迴圈的每次迭代中,intchan上都有一個準備好接收的值。

  • 啟動consumergoroutine 的 goroutine 已取消傳遞到consumer的上下文。因此,ctx.done()通道也有一個可供接收的值。

問題:

  • 在這種情況下,select 語句的兩種情況都已準備好運行。
  • 根據 go 之旅,select將隨機選擇一種情況,因為兩者都已準備好運行。
  • 如何保證select不會繼續選擇<- intchan案例?如果<- cx.done()案例在for 迴圈的每次迭代中都準備就緒,我們如何知道<- ctsx.done()案例最終會被選中?
func consumer(ctx context.context, intchan chan int) { for { select { case <-ctx.done(): return case i := <-intchan: foo(i) } } }
登入後複製

我嘗試在下面的程式中使用consumer函數。 在該程式的多次運行中,consumerproducergoroutine 似乎總是終止。

為什麼我們最終不會以<-ctx.done()案例從未執行的運行結束?

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: } } }
登入後複製

解決方法

沒有任何保證。保證終止的最簡單方法是在 select 語句之外使用ctx.err()檢查錯誤。將錯誤返回傳遞上下文的程式碼也很常見。我會這樣寫 consumer 函數:

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() }
登入後複製

以上是我們如何保證取消的上下文會導致 goroutine 終止?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:stackoverflow.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!