Go channel原理分析

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向管道一边写数据,一边读数据,此时协程分别位于两个等待队列中。

协程读取管道时的阻塞条件:

  1. 管道无缓冲区
  2. 管道缓冲区无数据,协程会加入recvq队列
  3. 管道的值为nil

协程写入管道时的阻塞条件:

  1. 管道无缓冲区
  2. 管道缓冲区已满,协程会加入sendq队列
  3. 管道的值为nil

关闭管道需要注意的点:

  1. 唤醒recvq中的协程获取的数据都为nil
  2. 唤醒sendq中的协程并且触发panic
    以下操作会触发panic:
    关闭nil的管道
    关闭已经关闭的管道
    向关闭的管道写入数据

select的case在读管道时不会阻塞,读不到数据直接返回。
for-range读取管道中的数据时,当管道中没有数据则会阻塞。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hewesH

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值