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中文网其他相关文章!