前言:

       很无聊,闲来无事看golang一些开源代码,发现有些人作为生产者把消息扔到channel就直接顺手给close掉了,也不等消费者消费完。有些惊奇,这不会丢数据么?按照字面上的意思,我既然close了,呢么消费者应该被唤醒退出。 但经过我的测试发了大量 ch <- data 之后,立马close的话,消费者还是照样会消费数据,不会因为close channel丢消息。

该文章后续仍在不断更新中, 请移步到原文地址 http://xiaorui.cc/?p=5007

     那么我们来分析下 channel 为什么不会丢数据 ?  涉及到原理性的话题,不要猜,只能看golang源码了。 golang channel源码里面的hchan结构,close方法及chanrecv方法就可以完美的解释刚才的问题。  channel源码地址, https://golang.org/src/runtime/chan.go,大家可以对照下源码。

Hchan

Hchan是channel的主要数据结构,我们关心的 qcount用来表示消息的个数,closed int32标识用来表示chan的开关,1为关闭.

Closechan

Closechan是chan.go里的关闭channel的方法,该方法除了将 c.closed 设置为 1。还需要唤醒 recvq和sendq 队列里面的阻塞 goroutine. 如果你不唤醒的化,因为没有生产者send数据,也就无法通过事件来唤醒goroutine,所以这时候需要把他们都唤醒起来,判断是否退出的逻辑。

Chanrecv

消费者接收事件相关的逻辑,不是简单的判断closed标志位,而且会判断channel消息个数…  就因为不好好看源码,导致我想让消费者退出的时候,用另外一个exit channel来通信,这样每个消费者用select监听两个channel,一个业务数据,一个通知退出…  

玩了几年channel,居然不知道这特性,也是醉了。 这里我给自己解释下,我开发的后端服务基本是那种channel作为队列常住的那样,不会像有些服务动不动就new一个channel,所以…. 

通过上面的channel源码,我们知道了channel是安全退出的。下面是我测试的脚本,我兴趣的可以跑跑。

总结:

     多看源码,多读书 .  golang社区里的源码质量大多质量比较高,建议大家多看点源码。 先前看了 golang nsq, boltdb, influxdb的一些源码,感触很多.  当你不知道该学点什么的时候,可以随意在github中闲逛下,总有点项目会让你眼前一亮。



对Python及运维开发感兴趣的朋友可以加QQ群 : 478476595 !!!
{ 2000人qq大群内有各厂大牛,常组织线上分享及沙龙,对高性能及分布式场景感兴趣同学欢迎加入该QQ群 }

另外如果大家觉得文章对你有些作用!   帮忙点击广告. 一来能刺激我写博客的欲望,二来好维护云主机的费用.
如果想赏钱,可以用微信扫描下面的二维码. 另外再次标注博客原地址  xiaorui.cc  ……   感谢!

说说golang goroutine并发时遇到死锁问题

Goroutine和channel是Go在“并发”方面两个核心feature。我自己在使用golang开发时会被常会被channel所困扰。废话不多说,正题开始. 那么golang的cha...

阅读全文

个人对于golang的goroutine并发处理任务时的理解

以前用golang做并发处理的时候,很是粗暴,就是利用golang的高级性能,直接fork一个任务,来处理请求,最典型的就是直接 go func,当时是因为用http和socke...

阅读全文

评论已关闭。