dongshan1396 2019-07-21 14:39
浏览 5
已采纳

在go例程之外向通道发送值时,go例程陷入僵局

I tried changing a little bit on the code when learning Go select statement in Golang tour: 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.

Thank you guys.

  • 写回答

1条回答 默认 最新

  • dongshan7708 2019-07-21 14:50
    关注

    The quit channel is an unbuffered channel. Communication on an unbuffered channel does not proceed until both a sending and receiving goroutine are ready. The statement quit <- 0 blocks before the application executes the function to receive the value. A receiving goroutine will never be ready

    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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 如何获取烟草零售终端数据
  • ¥15 数学建模招标中位数问题
  • ¥15 phython路径名过长报错 不知道什么问题
  • ¥15 深度学习中模型转换该怎么实现
  • ¥15 HLs设计手写数字识别程序编译通不过
  • ¥15 Stata外部命令安装问题求帮助!
  • ¥15 从键盘随机输入A-H中的一串字符串,用七段数码管方法进行绘制。提交代码及运行截图。
  • ¥15 TYPCE母转母,插入认方向
  • ¥15 如何用python向钉钉机器人发送可以放大的图片?
  • ¥15 matlab(相关搜索:紧聚焦)