channel原理分析
数据结构
type hchan struct {
qcount uint // 当前队列中剩余的元素个数
dataqsiz uint // 环形队列的长度,即为缓冲区的大小
buf unsafe.Pointer // 指向环形队列的指针
elemsize uint16 // 管道中元素的大小
closed uint32 // 管道是否关闭
elemtype *_type // 元素的类型
sendx uint // 元素写入管道时存放到队列中的下标位置,队尾
recvx uint // 指定下一个从管道中读取元素在队列中的位置,队首
recvq waitq // 等待读消息的协程队列
sendq waitq // 等待写消息的协程队列
lock mutex // 互斥锁,chan不允许并发读写
}
从管道读数据时,如果缓冲区为空或者没有缓冲区,则当前协程会被阻塞,并加入recvq队列。
向管道写入数据时,如果缓冲区已满或者没有缓冲区,则当前协程会被阻塞,并加入sendq队列。
一般情况recvq和sendq至少有一个为空,除了同一个协程使用select向管道一边写数据,一边读数据,此时协程分别位于两个等待队列中。
协程读取管道时的阻塞条件:
协程写入管道时的阻塞条件:
关闭管道需要注意的点:
select的case在读管道时不会阻塞,读不到数据直接返回。
for-range读取管道中的数据时,当管道中没有数据则会阻塞。