Channel 在运行时的内部表示是 runtime.hchan,该结构体中包含了一个用于保护成员变量的互斥锁,从某种程度上说,Channel 是一个用于同步和通信的有锁队列。
有很多试图通过各种方式 实现 无锁 Channel 的方案,但目前都还有各种各样问题尚不够完美.
所以实际上也借助了锁 (sync.Mutex)
Go 语言的 Channel 在运行时使用 runtime.hchan 结构体表示。在 Go 语言中创建新的 Channel 时,实际上创建的都是该结构体:
1 | type hchan struct { |
以下内容来自 Golang Channel 实现原理
hchan:channel 的底层数据结构
• qcount:当前 channel 中存在多少个元素;(q为queue的缩写)
• dataqsize: 当前 channel 能存放的元素容量;(环形队列的容量)
• buf:channel 中用于存放元素的环形缓冲区;
• elemsize:channel 元素类型的大小;
• closed:标识 channel 是否关闭;(为什么不用bool,或者int8)
• elemtype:channel 元素类型;
• sendx:发送元素进入环形缓冲区的 index;
• recvx:接收元素所处的环形缓冲区的 index;
• recvq:因接收而陷入阻塞的协程队列;
• sendq:因发送而陷入阻塞的协程队列;
通过什么实现阻塞?
1 | type waitq struct { |
waitq:阻塞的协程队列
• first:队列头部
• last:队列尾部
1 | type sudog struct { |
sudog:用于包装协程的节点
• g:goroutine,协程;
• next:队列中的下一个节点;
• prev:队列中的前一个节点;
• elem: 读取/写入 channel 的数据的容器;
• isSelect:标识当前协程是否处在 select 多路复用的流程中;
• c:标识与当前 sudog 交互的 chan.
原文链接: https://dashen.tech/2020/10/15/golang之channel进阶/
版权声明: 转载请注明出处.