並發中的死鎖錯誤:「拋出:所有Goroutine 都處於睡眠狀態」
在Go 中處理並發時,如果所有Goroutines 都處於休眠狀態,則可能會發生死鎖goroutine 正在等待彼此執行操作。與此問題相關的一個常見錯誤是「拋出:所有goroutine 都在睡眠- 死鎖!」
理解問題
考慮以下Go 程序:
package main import ( "fmt" ) func total(ch chan int) { res := 0 for iter := range ch { res += iter } ch <- res } func main() { ch := make(chan int) go total(ch) ch <- 1 ch <- 2 ch <- 3 fmt.Println("Total is ", <-ch) }
執行這個程式時,我們遇到錯誤「throw: all goroutine are sleep - deadlock!」原因是total函數中的範圍循環永遠不會退出,因為我們永遠不會關閉ch通道。結果,在 main 函數中等待接收結果的 goroutine 永遠不會收到它。
解決死鎖
要解決這個死鎖,我們需要關閉ch 通道指示不再發送任何值。此外,我們可以使用單獨的通道傳回結果,從而防止在同一通道上直接發送和接收。
下面修改後的程式解決了這些問題:
package main import ( "fmt" ) func total(in chan int, out chan int) { res := 0 for iter := range in { res += iter } out <- res // sends back the result } func main() { ch := make(chan int) rch := make(chan int) go total(ch, rch) ch <- 1 ch <- 2 ch <- 3 close(ch) // this will end the loop in the total function result := <-rch // waits for total to give the result fmt.Println("Total is ", result) }
透過關閉ch 通道並使用單獨的 rch 通道來獲取結果,我們消除了死鎖並允許程式正確執行。
以上是如何解決 Go 並發死鎖:「所有 goroutine 都在睡覺」?的詳細內容。更多資訊請關注PHP中文網其他相關文章!