源码地址:https://github.com/golang/go/blob/master/src/runtime/chan.go
type hchan struct {
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
elemsize uint16
closed uint32
elemtype *_type // element type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
// lock protects all fields in hchan, as well as several
// fields in sudogs blocked on this channel.
//
// Do not change another G's status while holding this lock
// (in particular, do not ready a G), as this can deadlock
// with stack shrinking.
lock mutex
}
qcount uint // 队列中的当前数据的个数
- dataqsiz uint // 环形队列长度,即可以存放的元素个数
- buf unsafe.Pointer // 存放数据的环形数组
- elemsize uint16 // 每个元素的大小
- closed uint32 // 表示 channel 是否关闭的标识位
- elemtype *_type // 队列中元素类型
- sendx uint // 当前发送元素的索引,指示元素写入时存放到队列中的位置
- recvx uint // 当前接受元素的索引,指示元素从队列的该位置读出
- recvq waitq // list of recv waiters 接收等待队列;由 recv 行为(也就是 <-ch)阻塞在 channel 上的 goroutine 队列
- sendq waitq // list of send waiters 发送等待队列;由 send 行为 (也就是 ch<-) 阻塞在 channel 上的 goroutine 队列
- lock mutex lock保护hchan中的所有字段,以及此通道上阻塞的sudoG中的几个字段。
waitq
发送及接收队列的结构体 等待队列的链表实现
type waitq struct {
first *sudog
last *sudog
}
对 G 的封装
type sudog struct {
// The following fields are protected by the hchan.lock of the
// channel this sudog is blocking on. shrinkstack depends on
// this for sudogs involved in channel ops.
g *g
selectdone *uint32 // CAS to 1 to win select race (may point to stack)
next *sudog
prev *sudog
elem unsafe.Pointer // data element (may point to stack)
// The following fields are never accessed concurrently.
// For channels, waitlink is only accessed by g.
// For semaphores, all fields (including the ones above)
// are only accessed when holding a semaRoot lock.
acquiretime int64
releasetime int64
ticket uint32
parent *sudog // semaRoot binary tree
waitlink *sudog // g.waiting list or semaRoot
waittail *sudog // semaRoot
c *hchan // channel
}
参考
https://www.cyhone.com/articles/analysis-of-golang-channel/
https://github.com/zboya/golang_runtime_reading/blob/master/src/runtime/chan.go