一、问题截图

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. NCF WebApi中 Controller的全解析

    简介 上一篇我们说了如何实现一个WebApi,并运行起来 这次我们来说说WebApi的内在,我们到底做了哪些事情 仓库地址:https://github.com/NeuCharFramework/NC ...

  2. [源码解析] 深度学习分布式训练框架 horovod (3) --- Horovodrun背后做了什么

    [源码解析] 深度学习分布式训练框架 horovod (3) --- Horovodrun背后做了什么 目录 [源码解析] 深度学习分布式训练框架 horovod (3) --- Horovodrun ...

  3. 『心善渊』Selenium3.0基础 — 1、Selenium自动化测试框架介绍

    目录 1.Selenium介绍 2.Selenium的特点 3.Selenium版本说明 4.拓展:WebDriver与Selenium RC的区别 5.Webdriver工作原理 1.Seleniu ...

  4. 【题解】Luogu P2875 [USACO07FEB]牛的词汇The Cow Lexicon

    题目描述 Few know that the cows have their own dictionary with W (1 ≤ W ≤ 600) words, each containing no ...

  5. Golang学习(用代码来学习) - 第二篇

    type Circle struct { radius float64 desc string } //定义结构体里面的方法 func (c Circle) getArea() float64 { r ...

  6. Ubuntu配置apt安装源为清华源[含自动配置脚本]

    Ubuntu配置apt安装源为清华源[含自动配置脚本] 一.备份原配置文件 Ubuntu 的软件源配置文件是/etc/apt/sources.list.将系统自带的该文件做个备份,以防万一. sudo ...

  7. js笔记22

    1.在拖拽元素的时候,如果元素的内部加了文字或者图片,拖拽效果会失灵? 浏览器会给文字和图片一个默认行为,当文字和图片被选中的时候,会有一个拖拽的效果,即使我们没有人为给他添加.所以当我们点击这个元素 ...

  8. Redis 底层数据结构之跳跃表

    文章参考 <Redis 设计与实现>黄建宏 Redis(2) 跳跃表 跳跃表 跳跃表 skiplist 是一种有序数据结构,它通过在每个节点中维持多个指向其他节点的指针,从而达到快速访问节 ...

  9. AcWing 1140. 最短网络

    农夫约翰被选为他们镇的镇长! 他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场. 约翰已经给他的农场安排了一条高速的网络线路,他想把这条线路共享给其他农场. 约翰的农场的编号是1,其他农场 ...

  10. 分布式唯一ID生成方案选型!详细解析雪花算法Snowflake

    分布式唯一ID 使用RocketMQ时,需要使用到分布式唯一ID 消息可能会发生重复,所以要在消费端做幂等性,为了达到业务的幂等性,生产者必须要有一个唯一ID, 需要满足以下条件: 同一业务场景要全局 ...