在goroutine中添加select default语句导致channel死锁求助
无缓冲Channel带default的Select导致死锁的原因分析
先拆解你的代码执行全程:
- 你创建的是无缓冲Channel,这种Channel的发送操作
ch <- 1必须等有接收方(也就是main goroutine里的<-ch)准备好接收,才能完成,否则会阻塞。 - 启动的子goroutine用了带
default的select:select的规则是,当所有case都无法立即执行时,会直接走default分支,不会阻塞等待。 - main goroutine一开始就执行
time.Sleep(2),这2秒内完全没准备接收Channel的数据。所以子goroutine跑起来后,ch <-1这个case无法立即执行(没人接),直接触发default,打印完就退出了——根本没往Channel里发数据。 - 2秒后main goroutine醒来,执行
<-ch尝试接收,但此时Channel是空的,也没有其他goroutine会往里面发数据,main goroutine就一直阻塞在这里。整个程序里所有goroutine都处于休眠等待状态,Go runtime就会抛出死锁错误。
为什么去掉default或time.Sleep(2)就正常?
- 去掉
default:子goroutine里的select会阻塞在ch <-1这个case上,一直等到main goroutine结束休眠、准备好接收。此时发送操作完成,打印send suc,main也能接收到数据,程序正常退出。 - 去掉
time.Sleep(2):main goroutine启动子goroutine后,立刻执行<-ch准备接收。此时子goroutine的ch <-1可以立即完成(因为接收方已经就绪),所以打印send suc,接收也正常,程序无阻塞。
内容的提问来源于stack exchange,提问作者hankeyyh
相关产品推荐
相关产品推荐

