golang死锁问题(fatal error: all goroutines are asleep - deadlock!)

这段代码运行没有问题,循环输出:call f1...

package main

import (
    "fmt"
)

func f1() {
    for {
        fmt.Println("call f1...")
    }
}

func f2() {
    fmt.Println("call f2...")
}

func main() {
    go f1()
    go f2()
    ch := make(chan int)
    <-ch
}

若注释掉go f1(),代码运行时提示死锁:

fatal error: all goroutines are asleep - deadlock!

代码如下:

package main

import (
    "fmt"
)

func f1() {
    for {
        fmt.Println("call f1...")
    }
}

func f2() {
    fmt.Println("call f2...")
}

func main() {
    // go f1()
    go f2()
    ch := make(chan int)
    <-ch
}

为什么同是调用协程,调用f1不会产生死锁,而调用f2会产生死锁。是因为f1有死循环么?按说没有协程往通道ch写,在main中读取ch应该都会产生死锁,是不是我理解错了,求解答。谢谢!

阅读 28.6k
5 个回答

已经提示很明确了,all goroutines are asleep,所有协程都在睡觉!
所以go就认为是死锁了。如果有f1的话,至少有一个协程是在干活的。

对于死锁的检测非常麻烦,或许go就采用了这种比较简单粗暴的方法。算是一个小bug吧,但是关系不大。

f1是死循环阻塞主线程,调用f1的时候还没执行ch := make(chan int) <-ch ,但是调用f2的时候 一次执行完毕,等待<-ch输出,没有载体接数据,所以就死锁了
我的理解

新手上路,请多包涵

没注释掉f1的时候,还有其他goroutine在跑,main goroutine中阻塞等待数据的<-ch有可能可以等到数据,所以没有死锁;
但是注释掉f1之后,当f2执行完之后就只剩main goroutine在跑,而这个main goroutine又阻塞了,所以就永远不可能有其它goroutine可以发送数据到ch中,这个main goroutine就会永远阻塞了,就产生死锁了

那是因为你第一段代码的

ch := make(chan int)  
<-ch

这个部分就没有被执行. 原因是啥我也不知道.

新手上路,请多包涵

不好意思 我来晚了

是因为你没关闭通道 你现在应该知道了吧

close(ch)

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏