写点什么

Go Channel 实例剖析

用户头像
非晓为骁
关注
发布于: 4 小时前

本文档主要通过实际例子,GO 版本 v1.16.6,结合 Go channel 的数据结构进行分析,hchan 里面的参数是怎么变化的,同时解析一下 hchan 里面 buf 的读与写,queue 是怎么运作的。想要了解 Go Channel 源码的可以看,我之前的博客《GO Channel 源码分析》https://xie.infoq.cn/article/f378a432b07f54af086c9e7ae


本文大纲如下,会先分析流程,数据结构,最后再实例:


  • channel send 流程图

  • channel read 流程图

  • hchan.buf 的读与写

  • hchan.recvq/sendq 的读与写

  • channel send 实例分析

  • channel recv 实例分析

channel send


  1. 判断 channel recvq 是否有正在等着 read 的 channel

  2. 如果有从 recvq 中 dequeue 一个出来 sudog(sg)

  3. 如果 sg 指向的 element 不为空,则把当前写入的 channel 的 value 给 sg,send 的数据直接拷贝到目标栈上

  4. 如果 sg 指向的 element 已经为空或者执行完第三步,则唤醒之前 park 住的 sg

  5. 如果第一步 recvq 为空,表示没有在等待 read 的 channel,则判断是否当前 channel 有缓存空间

  6. 有缓存空间则写入 buf 中

  7. 没有缓存空间则初始化一个 sudog,写入 sendq,并且 gopark 挂起

channel read

和 channel send 大同小异


  1. 判断 channel sendq 是否有正在等着 send 的 channel

  2. 如果有从 sendq 中 dequeue 一个出来 sudog(sg)

  3. 如果当前 channel 还有缓存空间,从 buf 中 copy

  4. 如果当前 channel 没有缓存空间,则直接把 recv 的数据 copy 给 sg,从 sender 的栈上拷贝数据

  5. 如果第一步 sendq 为空,表示没有在等待 send 的 channel,判断否当前 channel 有缓存空间

  6. 有缓存空间则从 buf 中读取

  7. 没有缓存空间则初始化一个 sudog,写入 recvq,并且 gopark 挂起

hchan.buf 读与写

channel 的 buf 其实就是一个环形队列,channel send 和 recv,分别是对 buf 的 write 和 read。write 的时候就是把写入 value 的地址 copy 到 buf 中对应的缓存地址去。read 就是把 buf 在源码中是通过 chanbuf 来计算出 read 和 write 的地址。


在 hcan 中,datasize,qcount,sendx 和 recvx 就是用来操作 buf 的参数。datasize 是 buf 的空间大小,qcount 是存储元素的数量,sendx 是写入时的地址下标,recvx 是读取时的地址下标。


hchan.recvq/sendq 的读与写

hchan 里面的 recvq 和 sendq 就是一个先进先出的 queue,enqueue 和 dequeue 可以通过下面的例子看一下。



channel send 实例分析

c:=make(chan int,2),chan type 为 int,缓存大小为 2


同一个颜色的就是一步



  1. c < 1:有缓存空间,写入缓存

  2. c < 1:缓存空间,写入缓存

  3. c < 1:缓存空间用完,gopark,写入 sendq

channel recv 实例分析

接着上个例子的结果



  1. = < c:sendq 中有值,dequeue 出来,写入 dequeue 的 channel

  2. = < c:缓存中有值,从缓存中读

  3. = < c:缓存中还有值,从缓存中读

  4. = < c:channel 没有缓存了,就写入 recvq,gopark

  5. c < 1:recvq 中有值,从 recvq dequeue,写入

用户头像

非晓为骁

关注

no pain no gain 2019.04.10 加入

用我的勤奋,一点一点地努力,提升自己的能力,拓展自己的视野,提高自己的认知。

评论

发布
暂无评论
Go Channel实例剖析