chan数据结构
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 接收消息goroutine队列,链表
sendq waitq // list of send waiters 发送消息goroutine队列,链表
// 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
}
环形队列
创建有缓冲区channel时,如下:
channel := make(chan int, 6) //6: 指定了channel的环形队列大小
等待队列
channel读写操作:
- 读:无缓冲区或缓冲区空,读goroutine阻塞,被挂起在channel的recvq队列中,直到被写goroutine唤醒
- 写:无缓冲区或缓冲区满,写goroutine阻塞,被挂起在channel的waitq队列中,直到被读goroutine唤醒
无缓冲区的channel结构如下:G阻塞读取数据
数据结构
//双向链表
type waitq struct {
first *sudog
last *sudog
}
//被阻塞的goroutine的封装
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
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
// isSelect indicates g is participating in a select, so
// g.selectDone must be CAS'd to win the wake-up race.
isSelect bool
parent *sudog // semaRoot binary tree
waitlink *sudog // g.waiting list or semaRoot
waittail *sudog // semaRoot
c *hchan // channel
}
类型信息
一个channel只能用于一种数据类型
- elemsize:标识元素大小,用于定位
- elemtype:标识元素类型
锁
lock实现锁:
- 消费者互斥读
- 生产者互斥写