golang chan source code reading
file
runtime/chan.go
prerequisites
unsafe.Pointerwaitqruntime.mutexsugogg
hchan
-
type hchan struct是 chan 的实现 -
简单理解的话就是使用两个 queue 分别处理
receive waiters和send waiters, 然后用一个buf unsafe.Pointer来作具体数据的缓冲
chansend
-
如果发现有
waiting receiver会把数据直接发给receiver不用去buf绕一圈 -
如果
buf足够就发送到buf -
如果
buf已经满了就sendq.enqueue(sg), 就会阻塞当前g
chanrecv
逻辑跟 chansend 类似
select 的处理
selectnbsend(c *hchan, elem unsafe.Pointer) (selected bool)
这段注释解释的非常清楚了// compiler implements // // select { // case c <- v: // ... foo // default: // ... bar // } // // as // // if selectnbsend(c, v) { // ... foo // } else { // ... bar // }-
selectnbrecv(elem unsafe.Pointer, c *hchan) (selected bool)
跟selectnbsend同样的处理方式, 编译时对代码做了一次转换 selectnbrecv2(elem unsafe.Pointer, received *bool, c *hchan) (selected bool)
稍微有一些不同// compiler implements // // select { // case v, ok = <-c: // ... foo // default: // ... bar // } // // as // // if c != nil && selectnbrecv2(&v, &ok, c) { // ... foo // } else { // ... bar // } //
Conclusion
chan 的实现逻辑非常清晰, 但是具体实现过程中有非常多的细节并不简单,
比如 lock 获取/释放, 关于 sudog 可能之后还会作一些笔记