Go Channel

Go Channel

Go语言采用CSP模型,让两个独立执行的程序通过消息传递的方式共享内存,Channel就是Golang用来完成消息通讯的数据类型。

结构定义

type hchan struct {
   qcount   uint           // 循环队列中所有数据总数
   dataqsiz uint           // 循环队列大小,固定的
   buf      unsafe.Pointer // 指向循环队列的指针
   elemsize uint16  // 循环队列中元素的大小
   closed   uint32  // chan是否关闭
   elemtype *_type // 循环队列中元素类型
   sendx    uint   // 已发送元素在循环队列中的位置
   recvx    uint   // 已读取元素在循环队列中的位置
   recvq    waitq  // 等待读取的goroutine队列
   sendq    waitq  // 等待发送的goroutine队列
   lock 	mutex  // chan互斥锁
}

type waitq struct {
  first *sudog
  last  *sudog
}

// qcount:chan中已经接收但还没被读取的元素的个数
// buf:用来存放chan接收的数据队列

// sendq 和 recvq 存储了当前 Channel 由于缓冲区空间不足而阻塞的 Goroutine 列表
// 这些等待队列使用双向链表 waitq 表示,链表中所有的元素都是 sudog 结构

在这里插入图片描述

分类

  • 无缓冲channel
没有定义chan的长度,可看作:"同步模式"
只有在两者都 ready 的情况下,数据才能在两者间传输(实际上就是内存拷贝)。
否则,任意一方先行进行发送或接收操作,都会被挂起,等待另一方的出现才能被唤醒。
  • 有缓冲channel
定义的chan有长度,可看作:"异步模式"
在缓冲槽可用的情况下(有剩余容量),发送和接收操作都可以顺利进行。
1.对已经空的chan进行读取时,会导致该goroutine阻塞
2.对已经满的chan进行写入时,会导致该goroutine阻塞
3.写入一个已关闭的chan会报错
4.读取一个已关闭的chan不会报错,chan为空读取为nil
5.关闭一个已关闭的chan会报错

读写

  • 初始化

    • 根据元素大小、是否含有指针决定存储空间的分配
    • 当元素大小为0时,只分配hchan结构体的内存就可以了
    • 当没有指针时,连续分配元素大小和结构体大小的内存
    • 当存在指针时,需要给指针元素单独分配内存空间
  • 写入数据
    请添加图片描述

    1. 先获取锁
    • 判断是否有待接收的协程(recvq中是非空),如果有的话,复制数据给此协程
    • 判断是否有空闲缓冲区,如果有的话,把数据复制到缓冲区
    • 否则把当前goroutine放入待发送队列(sendq)
    1. 释放锁
  • 读取数据
    请添加图片描述

    1. 先获取锁
    • 有待发送的协程,缓冲区中有数据,从缓冲队首取出数据,从sendq取出G,将G中数据放入缓冲队尾
    • 有待发送的协程,缓冲区中没有数据,从sendq取出G,读取G中数据
    • 没有待发送的协程,缓冲区中有数据,从缓冲队首取出数据
    • 没有待发送的协程,缓冲区中没有数据,将当前的G加入recvq排队,进入睡眠待唤醒
    1. 释放锁
  • 特性

    • 通道可以作为参数在函数中传递,当作参数传递时,复制的是引用。
    • 通道是并发安全的。
    • 同一个通道的发送操作之间是互斥的,必须一个执行完了再执行下一个。接收操作和发送操作一样。
    • 缓冲通道的发送操作需要复制元素值,然后在通道内存放一个副本。非缓冲通道则直接复制元素值的副本到接收操作。
    • 往通道内复制的元素如果是引用类型,则复制的是引用类型的地址。
  • 关闭原则

    1. 最好在写入端关闭
    2. 多个写入端,要保证只有一处关闭(可用chan)
  • select

    • select就是用来监听和channel有关的IO操作,当 IO 操作发生时,触发相应的动作
  • switch

    • 默认每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch, 但是可以使用fallthrough强制执行后面的case代码。
    • 加了fallthrough后,会直接运行【紧跟的后一个】case或default语句,不论条件是否满足都会执行
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值