• golang fatal error: all goroutines are asleep


    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

  • 相关阅读:
    软工5--结对2--四则运算生成器
    软工4——结对审查
    天数计算器
    翻转字符串
    位图排序
    软工 assignment 3 —— 求最大子数列之和
    剑指offer 面试题5.替换空格
    剑指offer 面试题4.二维数组中的查找
    剑指offer 面试题3.数组中重复的数字
    如何通过onenote发送博客到cnblog(博客园)
  • 原文地址:https://www.cnblogs.com/ghj1976/p/4295013.html
Copyright © 2020-2023  润新知