Golang -----channel

Channel

channel的作用

channel主要用于goroutine之间通讯和同步
设计思路是:不要通过共享内存来通讯,而是通过通讯来共享内存(前者就是传统的加锁,后者就是channel)

channel的底层数据结构

type hchan struct {
  //channel分为无缓冲和有缓冲两种。
  //对于有缓冲的channel存储数据,借助的是如下循环数组的结构
	qcount   uint           // 循环数组中的元素数量
	dataqsiz uint           // 循环数组的长度
	buf      unsafe.Pointer // 指向底层循环数组的指针
	elemsize uint16 //能够收发元素的大小
  

	closed   uint32   //channel是否关闭的标志
	elemtype *_type //channel中的元素类型
  
  //有缓冲channel内的缓冲数组会被作为一个“环型”来使用。
  //当下标超过数组容量后会回到第一个位置,所以需要有两个字段记录当前读和写的下标位置
	sendx    uint   // 下一次发送数据的下标位置
	recvx    uint   // 下一次读取数据的下标位置
  
  //当循环数组中没有数据时,收到了接收请求,那么接收数据的变量地址将会写入读等待队列
  //当循环数组中数据已满时,收到了发送请求,那么发送数据的变量地址将写入写等待队列
	recvq    waitq  // 读等待队列
	sendq    waitq  // 写等待队列


	lock mutex //互斥锁,保证读写channel时不存在并发竞争问题
}

在这里插入图片描述
总结hchan结构体的主要组成部分有四个:

  • 用来保存goroutine之间传递数据的循环链表。=====> buf。
  • 用来记录此循环链表当前发送或接收数据的下标值。=====> sendx和recvx。
  • 用于保存向该chan发送和从改chan接收数据的goroutine的队列。=====> sendq 和 recvq
  • 保证channel写入和读取数据时线程安全的锁。 =====> lock

未缓冲区channel就是数组长度为1的channel
缓存区channel就是数组长度大于1的channel

select 用法

go 的 select 为 golang 提供了多路 IO 复用机制,和其他 IO 复用一样,用于检测是否有读写事件是否 ready

  1. 仅支持channel,且单case:要么读,要么写
  2. 每个case的执行顺序是随机的<无序>
  3. 存在default,则select不会被阻塞。有一个case可以执行,也不会阻塞

Golang channel语句什么时候会被阻塞呢?

  1. 向未缓冲的channel发送数据(ch <- value)
  2. 从未缓冲的channel接收数据(value := <-ch)
  3. 向已满的缓冲channel发送数据
  4. 从空的缓冲channel接收数据
  5. select没有default时

思考

channel锁力度是多少?读写能并发吗?
由数据结构可以看出来,锁的力度是整个通道,读写实际是串形执行的
读写等待队列的作用是啥?是什么数据结构?
读写等待队列会在缓存区满的时候使用。 属于链式结构,存放的是goroutine,主要作用是保证gotoutine执行的顺序性.
缓存区满的时候明明会阻塞,那等待队列不是用一个元素就够了么?为啥是个链表?
因为可能会阻塞多个goroutine。这个时候需要保证被阻塞goroutine的顺序性
对一个已经关闭的channel读写元素会怎么样?
写操作会panic,读操作会立即返回(剩余数据/或者零值)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值