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

我们学习通道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。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Chapter 8 Goroutines and Channels Go enable two styles of...
    SongLiang阅读 5,526评论 0 3
  • fmt格式化字符串 格式:%[旗标][宽度][.精度][arg索引]动词旗标有以下几种:+: 对于数值类型总是输出...
    皮皮v阅读 4,780评论 0 3
  • channel[通道]是golang的一种重要特性,正是因为channel的存在才使得golang不同于其它语言。...
    码洞阅读 22,550评论 1 53
  • channel[通道]是golang的一种重要特性,正是因为channel的存在才使得golang不同于其它语言。...
    码洞阅读 6,700评论 0 51
  • 少小尝矜鸿鹄志,安知斗转暮残光。 徒泅块垒身何在,拓意盈胸绪里藏。 世事炎凉殇散聚,人情冷暖费思量。 狂歌饮马西风...
    周延龙阅读 3,490评论 4 13