为什么在全局范围内声明一个通道会导致死锁问题
Why declaring a channel in global scope gives deadlock issue
在 3 个代码片段中,带有在本地范围内声明的通道的代码片段有效,其他代码片段给出了死锁问题,之前的一个 answered SO question here says try to avoid declaring channel in the global scope. I checked in the official docs,但我没有找到任何解释。
虽然我没有阻止通道发送和接收,但为什么全局范围通道会出错?为什么我会在这里遇到死锁问题?
除了范围和初始化方面,make(chan int)
与 var myChan chan int
有何不同?
谁能更好地解释和建议 articles/documents/links/pdfs 在 Go 中有效地使用通道(并实现并发)?
(为简洁起见,片段中省略了导入和 'package main')
// 1. channel declared in global scope
var c chan int
func main(){
go send()
fmt.Println(<-c)
}
func send(){
c <- 42
}
//output: fatal error: all goroutines are asleep - deadlock!
// 2. channel declared in global scope + sending channel to goroutine
var c chan int
func main(){
go send(c)
fmt.Println(<-c)
}
func send(c chan int){
c <- 42
}
//output: fatal error: all goroutines are asleep - deadlock!
// 3. using channel as local scope and sharing it with goroutine
func main(){
c := make(chan int)
go send(c)
fmt.Println(<-c)
}
func send(c chan int){
c <- 42
}
因为通过声明未初始化的 var c chan int
,c
具有其类型的零值,在 chan
的情况下是 nil
。
如果您实际上 run your code,则错误消息会显示此信息。两个 goroutines 都是 sending/receiving on a nil
chan:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive (nil chan)]:
main.main()
/tmp/sandbox288806111/prog.go:11 +0x5c
goroutine 18 [chan send (nil chan)]:
main.send()
/tmp/sandbox288806111/prog.go:15 +0x39
created by main.main
/tmp/sandbox288806111/prog.go:10 +0x39
使用 make
而不是显式初始化变量 c
,这不是 nil
.
这与全局范围本身无关。事实上,如果你正确地初始化变量,例如var c chan int = make(chan int)
,即使在全局范围内,程序也不会死锁。
补充阅读:channel axioms (Dave Cheney)
If the channel is nil then the sender and receiver have no reference to each other; they are both blocked waiting on independent channels and will never unblock.
在 3 个代码片段中,带有在本地范围内声明的通道的代码片段有效,其他代码片段给出了死锁问题,之前的一个 answered SO question here says try to avoid declaring channel in the global scope. I checked in the official docs,但我没有找到任何解释。
虽然我没有阻止通道发送和接收,但为什么全局范围通道会出错?为什么我会在这里遇到死锁问题?
除了范围和初始化方面,
make(chan int)
与var myChan chan int
有何不同?谁能更好地解释和建议 articles/documents/links/pdfs 在 Go 中有效地使用通道(并实现并发)?
(为简洁起见,片段中省略了导入和 'package main')
// 1. channel declared in global scope
var c chan int
func main(){
go send()
fmt.Println(<-c)
}
func send(){
c <- 42
}
//output: fatal error: all goroutines are asleep - deadlock!
// 2. channel declared in global scope + sending channel to goroutine
var c chan int
func main(){
go send(c)
fmt.Println(<-c)
}
func send(c chan int){
c <- 42
}
//output: fatal error: all goroutines are asleep - deadlock!
// 3. using channel as local scope and sharing it with goroutine
func main(){
c := make(chan int)
go send(c)
fmt.Println(<-c)
}
func send(c chan int){
c <- 42
}
因为通过声明未初始化的 var c chan int
,c
具有其类型的零值,在 chan
的情况下是 nil
。
如果您实际上 run your code,则错误消息会显示此信息。两个 goroutines 都是 sending/receiving on a nil
chan:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive (nil chan)]:
main.main()
/tmp/sandbox288806111/prog.go:11 +0x5c
goroutine 18 [chan send (nil chan)]:
main.send()
/tmp/sandbox288806111/prog.go:15 +0x39
created by main.main
/tmp/sandbox288806111/prog.go:10 +0x39
使用 make
而不是显式初始化变量 c
,这不是 nil
.
这与全局范围本身无关。事实上,如果你正确地初始化变量,例如var c chan int = make(chan int)
,即使在全局范围内,程序也不会死锁。
补充阅读:channel axioms (Dave Cheney)
If the channel is nil then the sender and receiver have no reference to each other; they are both blocked waiting on independent channels and will never unblock.