Go 程式死鎖:「拋出:所有goroutine 都在睡眠」
在Go 程式中,當兩個或多個goroutine (並發運行的函數)無限期地等待彼此完成。使用通道時可能會出現一種這樣的情況,如以下程序所示:
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 goroutines are asleep - deadlock!
此問題的根本原因死鎖在於這樣一個事實:總goroutine 嘗試將一個值傳回它從(ch) 接收的相同通道。由於通道未關閉(發出完成訊號),整個 goroutine 中的範圍循環將無限期地繼續下去,從而阻塞任何進一步的發送或接收。
要解決此問題,我們可以引入另一個通道來接收結果。這是一個更新的程序:
package main import ( "fmt" ) func total(in chan int, out chan int) { res := 0 for iter := range in { res += iter } out <- res // Send result on separate channel } func main() { ch := make(chan int) rch := make(chan int) // New channel to receive result go total(ch, rch) ch <- 1 ch <- 2 ch <- 3 close(ch) // Explicitly close channel to end loop in `total` result := <-rch // Wait for result on `rch` fmt.Println("Total is ", result) }
透過在單獨的通道上發送結果並關閉原始通道,我們打破了僵局並允許主 goroutine 接收計算出的總數。
以上是為什麼我的 Go 程式會死鎖並出現'all goroutine are sleep”錯誤?的詳細內容。更多資訊請關注PHP中文網其他相關文章!