为了账号安全,请及时绑定邮箱和手机立即绑定

当向 Go 例程之外的通道发送值时,Go 例程会出现死锁

当向 Go 例程之外的通道发送值时,Go 例程会出现死锁

Go
慕田峪7331174 2023-07-04 19:05:56
我在 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 +0xa3goroutine 33 [chan receive]:main.main.func1(0xc000088000)        concurrency.go:24 +0x42created by main.main        concurrency.go:23 +0x89exit 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 onefunc 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)}输出是0quit您能解释一下执行第一个示例时死锁的根本原因是什么吗?在go例程中发送值退出通道与在主线程中发送值退出通道有什么区别?感谢你们。
查看完整描述

1 回答

?
宝慕林4294392

TA贡献2021条经验 获得超8个赞

该quit通道是无缓冲通道。在发送和接收 goroutine 都准备好之前,无缓冲通道上的通信不会继续。该语句quit <- 0在应用程序执行函数以接收值之前阻塞。接收 Goroutine 永远不会准备好


通过关闭通道修复:


c := make(chan int)

quit := make(chan int)

go func() {

    fmt.Println(<-c)

}()

close(quit)

fibonacci(c, quit)

...或者通过缓冲通道


c := make(chan int, 1) // <- note size 1

quit := make(chan int)

go func() { 

    fmt.Println(<-c) 

}()

quit <- 0   

fibonacci(c, quit)

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


查看完整回答
反对 回复 2023-07-04
  • 1 回答
  • 0 关注
  • 103 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信