gpt4 book ai didi

当向 go 例程之外的 channel 发送值时,go 例程会死锁

转载 作者:数据小太阳 更新时间:2023-10-29 03:40:22 28 4
gpt4 key购买 nike

在 Golang 之旅中学习 Go select 语句时,我尝试对代码进行了一些更改:https://tour.golang.org/concurrency/5 .但是,我遇到了问题:

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

这是我试过并得到问题的代码

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)
}

起初,我认为结果与下面代码的结果相同

//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)
}

输出是

0
quit

您能否解释一下执行第一个示例时出现死锁的根本原因是什么?在 go 例程中将值发送到退出 channel 与在主线程中将值发送到退出 channel 有什么区别。

谢谢你们。

最佳答案

quit channel 是一个无缓冲的 channel 。在发送和接收 goroutine 都准备好之前,无缓冲 channel 上的通信不会继续。声明quit <- 0在应用程序执行接收值的函数之前阻塞。接收 goroutine 永远不会就绪

通过关闭 channel 修复:

c := make(chan int)
quit := make(chan int)
go func() {
fmt.Println(<-c)
}()
close(quit)
fibonacci(c, quit)

...或者通过缓冲 channel

c := make(chan int, 1) // <- note size 1
quit := make(chan int)
go func() {
fmt.Println(<-c)
}()
quit <- 0
fibonacci(c, quit)

在这种情况下,fibonacci将在产生值之前退出。

关于当向 go 例程之外的 channel 发送值时,go 例程会死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57134195/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com