干货 all goroutines are asleep - d

2019-07-10  本文已影响0人  lucasgao

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

上一篇下一篇

猜你喜欢

热点阅读