原文: https://www.jianshu.com/p/147bd63801b6

--------------------------------------

Go与其他语言不一样,它从语言层面就已经支持并发,不需要我们依托Thread库新建线程。Go中的channel机制使我们不用过多考虑锁和并发安全问题。channel提供了一种goroutine之间数据流传输的方式。

今天我想从一个常见的deadlock error开始,讨论一下channel的特性。

如果运行以下程序:

var ch = make(chan int)

func main() {
ch <- 1
<-ch // 没有这行代码也会报同样的错误
}

terminal会报如下错误:

fatal error: all goroutines are asleep - deadlock!

回顾channel(信道)的概念,大致上来说,信道是goroutine之间相互沟通的管道,信道中数据的流通代表着goroutine之间内存的共享。宏观上来讲,信道有点像其他语言中的队列(queue),遵循先进先出的规则。

信道分为无缓冲信道(即unbuffered channel)和有缓冲信道(buffered channel)。对于无缓冲的信道来说,我们默认信道的发消息(send)和收消息(receive)都是阻塞(block)的。换句话来说,无缓冲的信道在收消息和发消息的时候,goroutine都处于挂起状态。除非另一端准备好,否则goroutine无法继续往下执行。

上面的那段程序便是一个明显的错误样例。在main函数执行到ch <- 1的时候main(也是一个goroutine)便已挂起,而并没有其他goroutine负责接收消息,而下面一句 <-ch 永远无法执行,系统便自动判为timeout返回error。这种所有线程或者进程都在等待资源释放的情况,我们便把它称之为死锁。

死锁是一个非常有意思的话题,常见的死锁大致分为以下几类:
i. 只在单一goroutine里操作信道,例子如上。
ii. 串联信道中间一环挂起,举例如下:

var ch1 chan int = make(chan int)
var ch2 chan int = make(chan int) func say(s string) {
fmt.Println(s)
ch1 <- <- ch2 // ch1 等待 ch2流出的数据
} func main() {
go say("hello")
<- ch1 // 堵塞主线
}

ch1等待ch2留出数据,然而ch2并没有发出数据导致goroutine阻塞,解决方案是给ch2喂数据:

func feedCh2(ch chan int) {
ch <- 2
}

iii. 非缓冲信道不成对出现:

c, quit := make(chan int), make(chan int)

go func() {
c <- 1 // c通道的数据没有被其他goroutine读取走,堵塞当前goroutine
quit <- 0 // quit始终没有办法写入数据
}() <- quit // quit 等待数据的写

当然,并非所有不成对出现的非缓冲信道都会报错:

func say(ch chan int) {
ch <- 1
} func main() {
ch := make(chan int)
go say(ch)
}

有意思的是,虽然say函数挂起等待信道接收消息,但是main goroutine并没有被阻塞,在main函数返回后程序依然可以自动终止。

关于缓冲信道将会在之后的文章中介绍,如有意见还请指教。

Reference: http://blog.csdn.net/kjfcpua/article/details/18265441

作者:Solonk8
链接:https://www.jianshu.com/p/147bd63801b6
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

[转]从Deadlock报错理解Go channel机制的更多相关文章

  1. caffe运行报错:datum channel>0(0:0)

    caffe在运行的时候报错:datum channel>0(0:0) 错误原因:数据通道错误,caffe不能识别 解决方案:不告诉你

  2. netty-websocket-spring-boot-starter关闭报错 io/netty/channel/AbstractChannel$AbstractUnsafe io/netty/util/concurrent/GlobalEventExecutor

    报错 java.lang.NoClassDefFoundError: io/netty/channel/AbstractChannel$AbstractUnsafe$ at io.netty.chan ...

  3. jmeter-利用While Controller控制器实现接口报错时的重试机制

    预期功能:在jmter脚本报错的时候重试,最多重试5次 1.添加While Controller 2.添加请求 3.添加断言,在断言不符合预期的时候加上代码:vars.put("status ...

  4. “ping”简单报错理解

    了解ABC类IP地址:网络.主机.子网.广播. ———————————————————————————- 学会ping: ping www.itxdm.me 网络检测:ping某一主机可以正常启动!( ...

  5. RedisCluster的rename机制失败报错,解决又是数据倾斜问题

    需求说明:spring session中的用户session更新是更新key的名字,所以对于key的操作时需要用newkey 替换oldkey value值只允许存在一个,这里用到rename就很合适 ...

  6. 从返回值未报错得到的对于java finally理解

    不多说了,直接看图 这个代码来自<深入理解java虚拟机(第二版)>,我在eclipse中编辑的,但是没有报错,一般来说,没有返回值,eclipse都会有个提示或者报错啥的,但是这个没有, ...

  7. Android报错:The content of the adapter has changed...与Channel is unrecoverably broken and will be disposed的分析与解决办法

    在Android中adapter错误: The content of the adapter has changed but ListView did not receive a notificati ...

  8. Force removing ActivityRecord,app died, no saved state报错的理解

    为什么说理解呢?出现这个问题,我的情景是,在activity里面直接起了一个Thread,线程里面进行了一个繁重的任务,当线程执行完后,这个activity也销毁了,界面显示的任务栈下面的一个活动.百 ...

  9. 从async await 报错Unexpected identifier 谈谈对上下文的理解

    原文首发地址: 先简单介绍下async await: async/await是ES6推出的异步处理方案,目的也很明确:更好的实现异步编程.   详细见阮大神 ES6入门 现在说说实践中遇到的问题:使用 ...

随机推荐

  1. windows批量导出文件名到txt

    做图像处理时,经常会遇到训练数据样本,这个时候一般就会要一个保存了大量文件名txt文件作为数据的输入 windows系统中可以直接使用dir,具体使用可以直接打开windows的终端 输入 dir/? ...

  2. webstorm 2019.1.3 破解

    2019.11.28日,已过期,出门右转 https://blog.csdn.net/ft_sunshine/article/details/92065158 1.修改host文件,末尾添加 0.0. ...

  3. K8S从入门到放弃系列-(3)部署etcd集群

    摘要:etcd 是k8s集群最重要的组件,用来存储k8s的所有服务信息, etcd 挂了,集群就挂了,我们这里把etcd部署在master三台节点上做高可用,etcd集群采用raft算法选举Leade ...

  4. LayUI笔记

    LayUI  经典模块化前端框架,低门槛开箱即用的前端 UI 解决方案.   其他UI框架:     Bootstrap,Element, EasyUI,LayUI 等等 LayUI使用  Layui ...

  5. Essential C++ Reading Notes

    Chapter1 P6, 1.2 Why //#include<string> we still can use "string user_name"? -->c ...

  6. vmware安装win7*64位时,安装不成功的关键点是光驱接口类型选择为IDE模式

    mware 安装win7*64时,找不到光盘,后来在xin7*64的虚拟机下的编辑虚拟机设置 找到光驱,点击高级,并选择IDE即可,这样就可以进入虚拟机找到光驱和硬盘到了.进入winpe后可以看到各种 ...

  7. spring cloud微服务实践七

    在spring cloud 2.x以后,由于zuul一直停滞在1.x版本,所以spring官方就自己开发了一个项目 Spring Cloud Gateway.作为spring cloud微服务的网关组 ...

  8. 跟我一起学编程—《Scratch编程》第24课:幸运大转盘

    同学你好,欢迎来到<跟我一起学编程>,我是包老师.这是<Scratch3.0编程>课程的第24课,我这节课教你做一个抽奖游戏:幸运大转盘. 学习目标: 1. 能够熟练使用造型工 ...

  9. asp.net core-13.Cookie-based认证实现

    1.打开visual studio code创建一个MVC项目

  10. asp.net MVC 抓取微信文章数据(正文)

    1.抓微信的正文主要是调用第三方的接口(https://market.aliyun.com/products/56928004/cmapi012134.html) using Newtonsoft.J ...