英文:
Select on time.After results deadlock
问题
以下是翻译的内容:
package main
import "time"
func main() {
chan_never_used := make(chan int, 10)
c := make(chan int, 10)
for {
select {
case <-time.After(time.Second):
c <- 0
case c <- <-chan_never_used:
}
println(<-c)
}
}
上面的代码会导致 fatal error: all goroutines are asleep - deadlock!
。
但是如果我改变一行代码:
package main
import "time"
func main() {
chan_never_used := make(chan int, 10)
c := make(chan int, 10)
for {
select {
case <-time.After(time.Second):
c <- 0
case n := <-chan_never_used: // 这行代码改变了
c <- n // 添加了这行代码
}
println(<-c)
}
}
它可以正常工作。
为什么第一个版本的代码会导致死锁,而这个改变可以使代码正常工作?
英文:
package main
import "time"
func main() {
chan_never_used := make(chan int, 10)
c := make(chan int, 10)
for {
select {
case <-time.After(time.Second):
c <- 0
case c <- <-chan_never_used:
}
println(<-c)
}
}
https://play.golang.org/p/7hZMdITecg
The code above results in fatal error: all goroutines are asleep - deadlock!
.
But if I change one line:
package main
import "time"
func main() {
chan_never_used := make(chan int, 10)
c := make(chan int, 10)
for {
select {
case <-time.After(time.Second):
c <- 0
case n := <-chan_never_used: // This line changed
c <- n // Add this line
}
println(<-c)
}
}
It works well.
Why the first version of code results in deadlock and why could this change make the code work?
答案1
得分: 2
根据标准,select语句由一系列的Send语句或Receive语句组成。
在这种情况下,是send语句。
send语句的定义如下:
SendStmt = Channel "<-" Expression .
Channel = Expression .
看看你的代码:
case c <- <-chan_never_used:
Channel
部分是 c
,Expression
部分是 <-chan_never_used
。
因此,send语句的select
语义(可能)不适用,因为是表达式造成了阻塞。在应用Send语句的语义之前,必须完全评估Expression部分。
英文:
As per the standard the select statement contains of a bunch of Send or Receive statements.
In this case it is the send statement.
Send statement is defined as:
SendStmt = Channel "<-" Expression .
Channel = Expression .
Looking at your code:
case c <- <-chan_never_used:
The Channel
fraction is c
, the Expression
fraction is <-chan_never_used
.
So, the select
semantics of the Send Statement of being (potentially) non-blocking is not applicable because it is the expression that blocks. And before the Send Statements semantics is applied the Expression part must be completely evaluated.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论