Go channel底层机制
此开源图书由ithaiq原创,创作不易转载请注明出处
channe通道源码如下
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
}
type waitq struct {
first *sudog
last *sudog
}
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
// isSelect indicates g is participating in a select, so
// g.selectDone must be CAS'd to win the wake-up race.
isSelect bool
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
}
hchan结构体解读:
hchan结构体是channel具体实现,其中主要字段buffer是一个循环队列,sendx和recvx用于接收buffer发送和接收的index,lock是互斥锁,sendq和recvq是表示等待阻塞列表。其他字段如qcount是队列剩余数量,dataqsize是缓冲区大小
此开源图书由github(ithaiq)原创,创作不易转载请注明出处
sudog结构解读:
当channel满了之后go协程阻塞后会生成一个sudog结构的数据,其中g是具体goroutine,elem是具体的数据,c是具体的channel通道
创建channel会在堆中分配内存,并返回指针。
使用环形循环队列作为缓冲区。
每次操作channel都会加锁,并更新sendx和recvx的index。
channel缓冲区满进入等待队列,让出M等待被唤醒
唤醒后重新加入G队列取出数据
最后更新于
这有帮助吗?