干货 all goroutines are asleep - deadlock 详尽案例分析

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

我们学习通道channel的时候,偶尔会在测试的时候遇到 all goroutines are asleep这样的panic错误,但是这个是怎么造成的呢。本文首先会介绍产生这个的原因,然后会结合具体案例进行详细分析。

错误原因

这个错误其实已经写的比较明白了,所有的 协程(goroutines)都处于休眠(阻塞)状态。当所有协程都处于阻塞状态的时候,那所有的协程都等不来解锁的那一天了,出现死锁,所以golang调度直接把这个给kill掉了。
简单来说出现这样的原因是主线程在阻塞,但是其他协程由于各种原因也阻塞了。

下面分享几个学习中遇到的案例

案例详解(持续更新)

案例一

代码如下:

package main

import (
    "fmt"
    "time"
)

func service1(ch chan string) {
    fmt.Println("BEEFORE")
    ch <- "from service1"
    fmt.Println("AFTER")
}

func main() {
    var ch chan string

    go service1(nil)
    fmt.Printf("sleep at :%d\n",time.Now().Unix())
    time.Sleep(time.Second * 2)
    fmt.Printf("weak at :%d\n",time.Now().Unix())
    for {
        select {
        case str := <-ch:
            fmt.Println(str)
        }
    }
}

执行结果如下:

➜  Q22 go run .
sleep at :1562689190
BEEFORE
weak at :1562689192
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [select (no cases)]:
main.main()
        /Users/gaoke/work/go/mine/Q22/main.go:23 +0x19a

goroutine 5 [chan send (nil chan)]:
main.service1(0x0)
        /Users/gaoke/work/go/mine/Q22/main.go:10 +0x7b
created by main.main
        /Users/gaoke/work/go/mine/Q22/main.go:17 +0x42
exit status 2

出现了我们期待的 all goroutines are asleep。可见所有线程都阻塞了,但是我们这个代码是想结果协程传来的字符串啊,为什么会阻塞呢。
这里就涉及了 协程的知识了,因为我们只是简单声明了下chanch 还是nil.

channelnil的时候,无论是传入数据还是取出数据,都会永久的block。

回到我们代码,因为chnil,所以在service1中这个协程被永久的阻塞了,当我们在select的时候又被阻塞了。这也就造成了所有协程阻塞,出现死锁,代码panic。


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

本文来自:简书

感谢作者:lucasgao

查看原文:干货 all goroutines are asleep - deadlock 详尽案例分析

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

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