一、问题截图

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()
/Users/dianjiu/Codes/go/src/go-learn/demo03/demo.go:36 +0x164 goroutine 18 [chan receive]:
main.consumer(0x140001020c0, 0x14000102060)
/Users/dianjiu/Codes/go/src/go-learn/demo03/demo.go:10 +0x148
created by main.main
/Users/dianjiu/Codes/go/src/go-learn/demo03/demo.go:31 +0x104
exit status 2 [Done] exited with code=1 in 10.226 seconds

二、问题代码

package main

import (
"fmt"
"strconv"
"time"
) func consumer(data chan int, done chan bool) {
for x := range data {
// println("recv:", x)
i := strconv.Itoa(x)
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "调用客户端"+i+"结束")
// <-data
}
done <- true
} func producer(data chan int, done chan bool, i, len int) {
x := strconv.Itoa(i)
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "调用客户端"+x+"开始")
//单个客户端处理时间为10秒
time.Sleep(time.Second * 10)
data <- i
} func main() {
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "开始了")
done := make(chan bool)
data := make(chan int)
go consumer(data, done)
for i := 0; i < 5; i++ {
go producer(data, done, i, 5)
} <-done
}

三、问题原因

出现上面协程死锁的原因是生产方法只会在data channel中放五个数据,消费方法在消费完这五个数据后,还会一直等待data channel有新的数据输入,无法结束。这样的话 Go就会判定为死锁。

四、问题解决

为了解决这个问题,我们在生产完五个数据后对data channel进行关闭,这样消费方法就可以正常退出了。

五、具体实现

利用sync.WaitGroup解决,在所有的 data channel 的输入处理之前,wg.Wait()这个goroutine会处于等待状态。当生产方法处理完后(wg.Done),wg.Wait()就会放开执行,执行后面的close(results)。

注意:要把wg.Add(1)放到go producer()外面。如果放到里面的话,(for i := 0; i < 5; i++)里的go producer()有可能会在wg.wait的go func之后执行,这样close(results)就会先执行。

package main

import (
"fmt"
"strconv"
"sync"
"time"
) var wg sync.WaitGroup func consumer(data chan int, done chan bool) {
for x := range data {
i := strconv.Itoa(x)
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "调用客户端"+i+"结束")
}
done <- true
} func producer(data chan int, done chan bool, i, len int) {
x := strconv.Itoa(i)
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "调用客户端"+x+"开始")
//单个客户端处理时间为10秒
time.Sleep(time.Second * 10)
data <- i
defer wg.Done()
} func main() {
fmt.Println(time.Now().Format("2006-01-02 15:04:05"), "开始了")
done := make(chan bool)
data := make(chan int)
go func() {
wg.Wait()
close(data)
}()
go consumer(data, done)
for i := 0; i < 5; i++ {
wg.Add(1)
go producer(data, done, i, 5)
} <-done
}

六、问题总结

所有 goroutine 在 main() 函数结束时会一同结束。

fatal error: all goroutines are asleep - deadlock!的更多相关文章

  1. golang fatal error: all goroutines are asleep - deadlock!

    转自:https://www.cnblogs.com/ghj1976/p/4295013.html http://blog.csdn.net/skh2015java/article/details/6 ...

  2. 4.Android 打包时出现的Android Export aborted because fatal error were founds [closed]

    Android 程序开发完成后,如果要发布到互联网上供别人使用,就需要将自己的程序打包成Android 安装包文件(Android Package,APK),其扩展名为.apk.使用run as 也能 ...

  3. PHP严重致命错误处理:php Fatal error: Cannot redeclare class or function

    1.错误类型:PHP致命错误 Error type: PHP Fatal error Fatal error: Cannot redeclare (a) (previously declared in ...

  4. Slave I/O: Got fatal error 1236

    [起因] 一次zabbix报警,从库[Warning] MySQL-repl was down  # 不知道主库/storage空间小于20%时为什么没有触发trigger [从库错误日志] 1611 ...

  5. “fatal error C1010”错误解决的三种方法

    尝试写了一个简单的类文件,但在编译的时候提示错误,具体错误信息如下: fatal error C1010: unexpected end of file while looking for preco ...

  6. "Fatal error: Call to undefined function: file_put_contents()"

    打开页面时提示这个错误: Fatal error: Call to undefined function: file_put_contents() 意思是请求未定义的函数,出现这个提示通常有两种情况: ...

  7. fatal error

    1.   fatal error C1083: 无法打开源文件 编译报此错误:  1>c1xx : fatal error C1083: 无法打开源文件:“Projects\XXXCCCC\VB ...

  8. LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏

    同时安装了VS2012和VS2010,用VS2010 时 >LINK : fatal error LNK1123: 转换到 COFF 期间失败: 文件无效或损坏 问题说明:当安装VS2012之后 ...

  9. (转)win7 64 安装mysql-python:_mysql.c(42) : fatal error C1083: Cannot open include file: 'config-win.h': No such file or directory

    原文地址:http://www.cnblogs.com/fnng/p/4115607.html 作者:虫师 今天想在在win7 64位环境下使用python 操作mysql 在安装MySQL-pyth ...

随机推荐

  1. jd一面面经

    1.讲一下hashmap原理. 2.concurrentHashMap的原理.concurrentHashMap和hashmap有什么不同? 3.synchnized底层实现?讲讲AQS 4.sync ...

  2. Django基础之模型层(01)

    内容概要 查询关键字 MySQL select    from    where    group by    having    order by    distinct    limit    r ...

  3. 合宙Luat直播间即将开启,你揭开行业奥秘,让你快人一步。

    嗨~刚陪你们过儿童节 和你们一起成长的合宙Luat 又有新计划 -- 合宙Luat官方直播即将开启 - 敬请关注 - - 官方直播什么内容 - 可能是合宙研发动态 可能是新品发布资讯 可能是行业大咖分 ...

  4. js 统计图插件chart.js

    chart是一个纯js插件,它功能强大小巧使用也很简单. 第一步引入 chart.js . <script type="text/javascript" src=" ...

  5. 如何利用Python计算景观指数AI

    可使用工具包 pylandstats 此工具包基本是根据fragstats形成的,大部分fragstats里面的景观指数,这里都可以计算.但是,还是有一小部分指数这里没有涉及. LS_METRICS ...

  6. 深入学习Netty(2)——传统NIO编程

    前言 学习Netty编程,避免不了从了解Java 的NIO编程开始,这样才能通过比较让我们对Netty有更深的了解,才能知道Netty大大的好处.传统的NIO编程code起来比较麻烦,甚至有遗留Bug ...

  7. 15、nginx编译安装

    15.1.nginx介绍: 1.Nginx是一个开源,支持高性能,高并发的www服务和代理服务软件,由俄罗斯人开发,是开源的,nginx因具有高并发(特别是静态的 资源).占用系统资源少等特性,且功能 ...

  8. Docker:如何修改Docker0网桥的默认网段

    1. 背景 Docker 服务启动后默认会创建一个 docker0 网桥(其上有一个 docker0 内部接口),它在内核层连通了其他的物理或虚拟网卡,这就将所有容器和本地主机都放到同一个物理网络. ...

  9. SpringCloud:Eureka注册中心设置显示IP路径

    未设置下的Eureka平台 可以看到Status显示的是 计算机名称! 解决方法: 在每一个需要注册的服务配置内加上如下几行配置 instance: prefer-ip-address: true # ...

  10. 前端集合传参,springmvc后端如何接收

    废话不多说,上代码 后端接收对象: class ObjectA{ private String a; private String b; private List<ObjectB> lis ...