为什么如下Go语言channel示例代码会触发deadlock死锁错误?
Go Channel死锁问题原因解析
问题复现代码
package main import "fmt" func main() { c := make(chan int) c <- 5 a := <- c fmt.Println(a) }
报错信息
fatal error: all goroutines are asleep - deadlock!
死锁根本原因
- 你声明的是无缓冲channel,无缓冲channel的发送、接收操作都必须有另一个对应的协程配合才能完成,单独在同一个协程内先后执行发送、接收操作必然会触发阻塞:
- 代码执行到
c <- 5这一行时,整个程序只有main协程在运行,没有其他协程从这个channel接收数据,所以发送操作会直接把main协程挂起阻塞,后续的a := <-c代码完全没有执行机会 - 整个Go进程里只有main这一个协程,它被永久阻塞后,调度器找不到其他可运行的协程,就会判定为死锁,抛出对应报错
- 代码执行到
可选修复方案
你可以任选一种方式解决死锁问题:
- 改用带缓冲的channel,缓冲区大小至少设为1:把
c := make(chan int)修改为c := make(chan int, 1),发送数据时只要缓冲区没满就不会阻塞,后续读操作可以正常从缓冲区取数 - 新增协程配合收发操作:比如先启动子协程执行接收操作,再在main协程发送数据,逻辑示例如下:
package main import "fmt" func main() { c := make(chan int) // 启动子协程先处理接收逻辑 go func() { a := <-c fmt.Println(a) }() c <- 5 }
内容的提问来源于stack exchange,提问作者IcanCode
相关产品推荐
相关产品推荐

