一、问题截图

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. Python 5种方法实现单例模式

    基本介绍 一个对象只允许被一次创建,一个类只能创建一个对象,并且提供一个全局访问点. 单例模式应该是应用最广泛,实现最简单的一种创建型模式. 特点:全局唯一,允许更改 优缺点 优点: 避免对资源的多重 ...

  2. 这 7 个 Linux 命令,你是怎么来使用的?

    使用 Linux 系统的开发者,很多人都有自己喜欢的系统命令,下面这个几个命令令是我平常用的比较多的,分享一下. 我不会教科书般的罗列每个指令的详细用法,只是把日常开发过程中的一些场景下,经常使用的命 ...

  3. Rethinking Training from Scratch for Object Detection

    Rethinking Training from Scratch for Object Detection 一. 概述 正常训练目标检测的流程分为以下几种: 在imagenet上进行预训练,然后在特定 ...

  4. 安全Web服务器

    https协议: 443 端口 虚拟Server0: 1.部署 网站证书(营业执照)# cd /etc/pki/tls/certs/ # wget http://classroom.example.c ...

  5. 微信小程序 -- 基于 movable-view 实现拖拽排序

    微信小程序 -- 基于 movable-view 实现拖拽排序 项目基于colorui样式组件 ColorUI组件库 (color-ui.com) 1.实现效果 2. 设计思路 movable-vie ...

  6. WEB安全新玩法 [1] 业务安全动态加固平台

    近年来,信息安全体系建设趋于完善,以注入攻击.跨站攻击等为代表的传统 Web 应用层攻击很大程度上得到了缓解.但是,Web 应用的业务功能日益丰富.在线交易活动愈加频繁,新的安全问题也随之呈现:基于 ...

  7. 【题解】Luogu P2214 [USACO14MAR]哞哞哞Mooo Moo

    P2214 [USACO14MAR]哞哞哞Mooo Moo 题目描述 Farmer John has completely forgotten how many cows he owns! He is ...

  8. 小白学k8s(9)-gitlab-runner实现go项目的自动化发布

    gitlab构建CI/CD 准备 docker部署gitlab 使用二进制部署gitlab-runner gitlab-runner注册 配置Variables 简单先来个测试 开始构建 遇到的报错 ...

  9. Kubernetes中予许及限制(PodSecurityPolicy)使用宿主机资源

    1.在pod中使用宿主机命名空间.端口等资源 pod中的容器通常在分开的Linux命名空间中运行.这些命名空间将容器中的进程与其他容器中,或者宿主机默认命名空间中的进程隔离开来. 例如,每一个pod有 ...

  10. rabbitmq概念简介

    AMQP协议 AMQP: Advanced Message Queue,高级队列协议. 特征: 这是一个在进程间传递异步消息的网络协议,因此数据的发送方.接收方以及容器(MQ)都可以在不同的设备上. ...