英文:
Channel deadlocks when I add select default statement in goroutine
问题
我正在学习通道,并且以下是我尝试的一个测试,但发生了死锁。
func main() {
ch := make(chan int)
go func() {
select {
case ch <- 1:
fmt.Println("send suc")
default: // 如果注释掉这一行,代码将正常运行
fmt.Println("default")
}
}()
time.Sleep(2) // 做一些耗时的操作...
fmt.Printf("receive val: %d", <-ch)
}
我原本期望不会发生死锁,但结果是:
default
fatal error: all goroutines are asleep - deadlock!
但是如果我移除 default
或者 time.Sleep(2)
,代码将正常运行,结果为:
send suc
receive val: 1
有人可以解释一下为什么会发生死锁吗?
英文:
I'm learning channel and below is a test I tried, but deadlock happens
func main() {
ch := make(chan int)
go func() {
select {
case ch <- 1:
fmt.Println("send suc")
default: // if comment this line, it will run smoothly
fmt.Println("default")
}
}()
time.Sleep(2) // do some time consuming thing...
fmt.Printf("receive val: %d", <-ch)
}
I expected there is no deadlock, but result is:
default
fatal error: all goroutines are asleep - deadlock!
But if I remove default
or time.Sleep(2)
, code will run smoothly, result:
send suc
receive val: 1
Can someone explain why deadlock happen?
答案1
得分: 6
你有一个带有default
的select
语句,这意味着如果没有任何通信操作准备就绪,select
不会等待,不会阻塞,而是立即执行default
分支。通道是无缓冲的,因此发送操作不准备就绪(因为没有接收方准备就绪 - main
正在休眠)。
因此,一旦main
中的休眠结束,它尝试从通道接收数据,但此时没有任何人试图在通道上发送数据。发生了死锁。
英文:
You have a select
with default
, that means if none of the communication ops are ready, select
will not wait, will not block, but execute default
immediately. The channel is unbuffered, so the send on it is not ready (because there are no receivers ready – main
is sleeping).
So once the sleep is over in main
, it tries to receive from the channel, but by then there is nobody trying to send on it. Deadlock.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论