[英]Go routines are deadlock when sending value to channel outside the go routines
I tried changing a little bit on the code when learning Go select statement in Golang tour: https://tour.golang.org/concurrency/5 .在 Golang tour 中学习 Go select 语句时,我尝试对代码进行一些更改: https ://tour.golang.org/concurrency/5。 However, i got issue:
但是,我遇到了问题:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.main()
concurrency.go:26 +0xa3
goroutine 33 [chan receive]:
main.main.func1(0xc000088000)
concurrency.go:24 +0x42
created by main.main
concurrency.go:23 +0x89
exit status 2
Here is the code i tried and got the issue这是我尝试并遇到问题的代码
func fibonacci(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x: //sending value x into channel c
x, y = y, x+y
case <-quit: //receive value from quit
fmt.Println("quit")
return
}
}
}
func main() {
//create two channels
c := make(chan int)
quit := make(chan int)
go func() { //spin off the second function in order to let consume from c , so fibonaci can continue to work
fmt.Println(<-c) //read value from channel c
}()
//Try moving the statement that send value to channel quit in order to
//return function fibonacci
quit <- 0
fibonacci(c, quit)
}
At first, i thought that the result will be same with result of below code起初,我认为结果将与以下代码的结果相同
//function fibonacci is same with the first one
func fibonacci(c, quit chan int) {
x, y := 0, 1
for {
select {
case c <- x: //sending value x into channel c
x, y = y, x+y
case <-quit: //receive value from quit
fmt.Println("quit")
return
}
}
}
func main() {
//create two channels
c := make(chan int)
quit := make(chan int)
go func() { //spin off the second function in order to let consume from c , so fibonaci can continue to work
fmt.Println(<-c) //read value from channel c
quit <- 0 //CHANGE: move the statement inside the closure function
}()
fibonacci(c, quit)
}
The output is输出是
0
quit
Can you please explain what's the root cause of deadlock when executing the first example?你能解释一下执行第一个例子时死锁的根本原因是什么吗? And what are differences when sending value to quit channel in the go routines with sending value to quit channel in the main thread.
在 go 例程中发送值到退出通道与在主线程中发送值到退出通道有什么区别。
Thank you guys.谢谢你们。
The quit
channel is an unbuffered channel. quit
通道是一个无缓冲通道。 Communication on an unbuffered channel does not proceed until both a sending and receiving goroutine are ready.在发送和接收 goroutine 都准备好之前,无缓冲通道上的通信不会继续。 The statement
quit <- 0
blocks before the application executes the function to receive the value.在应用程序执行函数以接收值之前,语句
quit <- 0
阻塞。 A receiving goroutine will never be ready接收 goroutine 永远不会准备好
Fix by closing the channel:通过关闭通道修复:
c := make(chan int)
quit := make(chan int)
go func() {
fmt.Println(<-c)
}()
close(quit)
fibonacci(c, quit)
... or by making the channel buffered ...或通过使通道缓冲
c := make(chan int, 1) // <- note size 1
quit := make(chan int)
go func() {
fmt.Println(<-c)
}()
quit <- 0
fibonacci(c, quit)
In this scenario, fibonacci
will quit before yielding a value.在这种情况下,
fibonacci
将在产生值之前退出。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.