专栏首页吴亲强的深夜食堂彻底搞懂channel原理(一)
原创

彻底搞懂channel原理(一)

图片拍摄于2021年10月3日,我的信仰。

躺的太久,该起床了。

宁可我卷死别人,不能让别人卷我。

之前断断续续看过Go几个模块的源码,可从未下笔,导致有些细节记不起来了。打算写一系列文章重新记录。

channel源码解析的文章太多了。一篇文章的长篇大论大部分人没耐心看完,所以我打算分开写,最后附上完整的ppt

当然这其中不会涉及过多细节源码,因为有时候,细节是魔鬼。

介绍

channel一些基础介绍这里就不过多涉及了,都1202年了,我不相信用过Go的人没用过channel

当然下图也涵盖了大部分使用姿势。

有一道使用channel进行任务编排的经典的题。题目如下:

有四个goroutine,编号为 1、2、3、4。每秒钟会有一个 goroutine打印自己的编号。请你实现这个程序,让输出的编号总是按照 1、2、3、4、1、2、3、4、……的顺序打印出来。就像这样,

可以自己先思考下,代码也可以通过后台回复击鼓传花获取。

原理解析

从一个简单的例子说起。

创建一个main.go文件,代码如下,

我们来看看这段代码编译以后长啥样。

想得到go程序的汇编代码并不难。

可以使用go tool compile -N -l -S main.go生成汇编代码:

或者使用go tool compile -N -l main.go先编译出代码,然后再使用go tool objdump main.o反汇编出代码。

还可以通过go build -gcflags -S main.go同样可以得到汇编的代码。

上面两种我就不演示了,可以自行实验。他们之中flag的具体含义也可以自行了解。

如果你觉得上面要自己敲代码比较麻烦,我推荐一个更加直接可视化的工具。

综上,从编译的代码我们可以看出,上述初始化一个channel,

ch := make(chan struct{})

实际上调用的是runtime.makechan

从函数中,我们能知道最终返回一个runtime.hchan的指针。

runtime.hchan结构。

我们先来解释hchan结构体各个字段的含义,之后在案例介绍中会更加详细的说明他们的作用。

先来看qcountdataqsiz有什么区别?

你去银行办事,银行有5个办事窗口,那么dataqsiz就等于5。在这里体现的是channel的容量为5。去银行的时候,当前有3个窗口有人正在办事,那么qcount就等于3,体现channel当前有3个数据元素。那么此时银行还可以再接待2个客户,对应还可以往channel发送2个数据元素。

其他字段现在看看说明就行了,后面会细讲。

到这里我们就知道创建一个channel本质上就是得到一个runtime.hchan的指针,后续对此chan的操作,无非就是对结构体字段进行相对应的操作。

同时我们也能猜出,为啥channel能在不同的g中传递消息,而对于使用者来说不用担心并发的问题。

其实就是hchan内部使用互斥锁来保证了并发安全。

最后我们来看一下runtime.makechan函数核心实现,当然注释已经很明白了。

可以看到创建的时候有一段switch分支代码,那么什么情况下会走对应的case呢?

根据上面的信息,我们可以得出,

  • 如果创建一个无缓冲channel ,那么只需要为runtime.hchan本身分配一段内存空间即可。
  • 如果创建的缓冲channel存储的类型不是指针类型,会为当前channel和存储类型元素的缓冲区,分配一块连续的内存空间。
  • 在默认情况下(缓冲channel存储类型包含指针),会单独为runtime.hchan和缓冲区分配内存。

总结

这篇我们主要介绍了如何获取go程序的汇编代码,通过汇编代码知道创建channel的具体函数runtime.makechan

同时我们还知道不同的创建姿势会导致走向不同的内存空间分配逻辑。

最后通过创建函数我们知道channel在程序运行时是使用runtime.hchan来表示。

下一篇彻底搞懂channel原理(二)

如果文章对你有所帮助,点赞、转发、留言都是一种支持!

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 彻底搞懂channel原理(三)

    上一篇文章主要通过一个现实例子间接反映channel的一些原理。最后一篇开始介绍一些细节,会涉及到源码。

    吴亲库里
  • 彻底搞懂channel原理(二)

    上一篇文章彻底搞懂channel原理(一)主要介绍channel运行时是通过hchan表示的,也简单说明了hchan各个字段的含义。

    吴亲库里
  • 一文彻底搞懂 HTTPS 的工作原理!

    当你打开浏览器,访问某个网站,如果网址旁有个小锁,代表访问的网址是安全的,反之不安全。当我们没有看到那个小锁的小图标的时候,需要提高警惕,不要随意输入个人重要的...

    杰哥的IT之旅
  • 彻底搞懂MyBatis插件原理及PageHelper原理

    提到插件,相信大家都知道,插件的存在主要是用来改变或者增强原有的功能,MyBatis中也一样。

    公众号 IT老哥
  • 看完让你彻底搞懂Websocket原理

    杭州前端工程师
  • 彻底搞懂NIO效率高的原理

    这篇文章读不懂的没关系,可以先收藏一下。笔者准备介绍完epoll和NIO等知识点,然后写一篇Java网络IO模型的介绍,这样可以使Java网络IO的知识体系更加...

    全菜工程师小辉
  • 手写mybatis彻底搞懂框架原理

    mybatis的前身是iBatis,其源于“Internet”和“abatis”的组合,是一款优秀的持久层框架,它支持定制化SQL、存储过程以及高级映射。myb...

    全菜工程师小辉
  • 一文彻底搞懂“内存管理”

    笔者面试过不少业务后台开发候选人,当问起内存管理的相关问题时,往往都会答出 JVM 的垃圾回收机制,并对 Serial、Parallel、CMS 等收集器如数家...

    CloudBest
  • 这一次彻底搞懂:分布式系统原理

    在具体的工程项目中,一个节点往往是一个操作系统上的进程。在本文的模型中,认为节点是一个完整的、不可分的整体,如果某个程序进程实际上由若干相对独立部分构成,则在模...

    大数据技术架构
  • 一文彻底搞懂OkHttp

    一直都想写一篇有关OkHttp的源码文章,今天推荐一篇关于解析OkHttp源码的文章,希望大家能有所收获。

    Rouse
  • 彻底搞懂彩虹表的实现原理

    7788的术语我就不多说了,简而言之,就是一种破解md5或者sha1这种哈希散列算法的一种办法。

    诺浅
  • 带你彻底搞懂-View的工作原理!

    1.ViewRoot对应ViewRootImpl类,是连接WindowManager和DecorView的纽带。View的三大流程是通过ViewRoot完成的。...

    胡飞洋
  • 彻底搞懂epoll高效运行的原理

    这篇文章读不懂的没关系,可以先收藏一下。笔者准备介绍完epoll和NIO等知识点,然后写一篇Java网络IO模型的介绍,这样可以使Java网络IO的知识体系更加...

    全菜工程师小辉
  • 彻底搞懂Object.defineProperty

    早在大半年前,掘金某位用户分享的面试题整理中有一题,简述let与const区别,你能自己模拟实现它们吗?,题目意思大概如此,时间久远我也很难找到那篇文章,当时看...

    zz_jesse
  • 彻底搞懂 Object.defineProperty

    早在大半年前,掘金某位用户分享的面试题整理中有一题,简述let与const区别,你能自己模拟实现它们吗?,题目意思大概如此,时间久远我也很难找到那篇文章,当时看...

    coder_koala
  • 彻底搞懂ArrayList

    同样是空的数组对象,和EMPTY_ELEMENTDATA区别在于,无参构造函数的空数组会用DEFAULTCAPACITY_EMPTY_ELEMENTDATA赋值...

    每天学Java
  • 一篇文章彻底搞懂Mysql事务相关原理

    引言redo log 与 undo log介绍redo logundo logmysql锁技术共享锁和排他锁意向锁记录锁间隙锁下一键锁插入意图锁自动上锁空间索引...

    35岁程序员那些事
  • 一文带你彻底搞懂JavaScript原型链

    Brendan Eich(布兰登·艾奇) 作为JavaScript的作者曾说过 “它是C语言和Self语言一夜情的产物。”

    童欧巴
  • 一文彻底搞懂kotlin inline

    Kotlin语言相信大家已经玩的很溜了,但大家有没有注意到它内部源码大量使用了inline,那么Kotlin为什么要使用inline?它的作用又是什么呢?

    Rouse

扫码关注云+社区

领取腾讯云代金券