步对象,因此一个对象可能有许多 sudog:chan 在不同的 gorouting 中传递等待
完整的发送和接受方法实现如下:
func chansend(c *hchan, ep unsafe.Pointer, block bool) bool {
// 获取 chan 的锁
lock(&c.lock)
// 检查 chan 是否已经关闭
if c.closed != 0 {
unlock(&c.lock)
panic("send on closed channel")
}
// 计算发送位置
i := c.sendx
// 计算队列中的元素数量
if c.qcount < c.dataqsiz {
c.qcount++
} else {
// 如果队列已满,需要将当前 goroutine 加入到发送等待队列中
g := getg()
gp := g.m.curg
if !block {
unlock(&c.lock)
return false
}
// 创建一个 sudog,表示当前 goroutine 等待发送
sg := acquireSudog()
sg.releasetime = 0
sg.acquiretime = 0
sg.g = gp
sg.elem = ep
sg.c = c
// 将 sudog 加入到发送等待队列中
c.sendq.enqueue(sg)
// 释放锁,并将当前 goroutine 阻塞
unlock(&c.lock)
park_m(gp, waitReasonChanSend, traceEvGoBlockSend, 1)
// 当 goroutine 被唤醒时,重新获取锁
lock(&c.lock)
// 检查 chan 是否已经关闭
if c.closed != 0 {
unlock(&c.lock)
panic("send on closed channel")
}
&