golang fatal error: all goroutines are asleep - deadlock!

ghj1976 · · 11323 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

channel默认上是阻塞的,也就是说,如果Channel满了,就阻塞写,如果Channel空了,就阻塞读。阻塞的含义就是一直等到轮到它为止。单有时候我们会收到 fatal error: all goroutines are asleep - deadlock!  异常,这是如何呢?

代码例子:

package main

import "fmt"

func main() {
    channel := make(chan string, 2)

    fmt.Println("1")
    channel <- "h1"
    fmt.Println("2")
    channel <- "w2"
    fmt.Println("3")
    channel <- "c3"    // 执行到这一步,直接报 error
    fmt.Println("...")
    msg1 := <-channel
    fmt.Println(msg1)
}

执行效果:

image

参考:

http://stackoverflow.com/questions/26927479/go-language-fatal-error-all-goroutines-are-asleep-deadlock

 

fatal error: all goroutines are asleep - deadlock!

出错信息的意思是:
在main goroutine线,期望从管道中获得一个数据,而这个数据必须是其他goroutine线放入管道的
但是其他goroutine线都已经执行完了(all goroutines are asleep),那么就永远不会有数据放入管道。
所以,main goroutine线在等一个永远不会来的数据,那整个程序就永远等下去了。
这显然是没有结果的,所以这个程序就说“算了吧,不坚持了,我自己自杀掉,报一个错给代码作者,我被deadlock了”

 

这里是系统自动在除了主协程之外的协程都关闭后,做的检查,继而报出的错误, 证明思路如下, 在100秒内, 我们看不到异常, 100秒后,系统报错。

package main

import (
    "fmt"
    "time"
)

func main() {
    channel := make(chan string, 2)

    go func() {
        fmt.Println("sleep 1")
        time.Sleep(100 * time.Second)
        fmt.Println("sleep 2")
    }()

    fmt.Println("1")
    channel <- "h1"
    fmt.Println("2")
    channel <- "w2"

    fmt.Println("3")
    channel <- "c3"

    fmt.Println("...")
    msg1 := <-channel
    fmt.Println(msg1)
}

100秒内执行效果截图:

image

100秒后执行效果截图:

image

 

如果避免上面异常抛出呢?这时候我们可以用 select来帮我们处理。

package main

import "fmt"

func main() {
    channel := make(chan string, 2)

    fmt.Println("1")
    channel <- "h1"
    fmt.Println("2")
    channel <- "w2"

    fmt.Println("3")
    select {

    case channel <- "c3":
        fmt.Println("ok")
    default:
        fmt.Println("channel is full !")
    }

    fmt.Println("...")
    msg1 := <-channel
    fmt.Println(msg1)
}

执行效果:

image

这时候,我们把第三个要写入的 chan 抛弃了。

 

上面的例子中是写的例子, 读的例子也一样,下面的异常是  ws := <-channel 这一行抛出的。

channel := make(chan string, 2)

fmt.Println("begin")
ws := <-channel
fmt.Println(ws)

image


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:ghj1976

查看原文:golang fatal error: all goroutines are asleep - deadlock!

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

11323 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传