高并发下的通信方式:Channel管道

高并发下的通信方式:Channel管道

内存与通信

  • “不要通过共享内存的方式进行通信”
  • “而是应该通过通信的方式共享内存”

为什么使用通信来共享内存

  • 避免协程竞争和数据冲突的问题。
  • 更高级的抽象,降低开发难度,增加程序可读性。
  • 模块之间更容易解耦,增强扩展性和可维护性。

如何设计高性能Channel

在这里插入图片描述
在这里插入图片描述

  • 环形缓存可以大幅降低GC的开销。
    在这里插入图片描述

hchan结构体中的互斥锁成员

  • 互斥锁并不是用来排队发送/接收数据的
  • 互斥锁保护的是hchan结构本身。
  • Channel并不是无锁的。
    在这里插入图片描述

Channel发送数据的底层原理是什么?

c <- 关键字

  • c <- 关键字是一个语法糖
  • 编译阶段,会把c <- 转化为runtime.chansend1()
  • chansend1()会调用chansend()方法
    在这里插入图片描述
直接发送
  • 发送数据前,已经有G在休眠等待接收。
  • 此时缓存肯定是空的,不用考虑缓存。
  • 将数据直接拷贝给G的接收变量,唤醒G。
  • 从队列里取出一个等待接收的G
  • 将数据直接拷贝到接收变量中
  • 唤醒G
放入缓存
  • 没有G在休眠等待,但是有缓存空间。
  • 将数据放入缓存
  • 获取可存入的缓存地址。
  • 存入数据
  • 维护索引
休眠等待
  • 没有G在休眠等待,而且没有缓存或满了。
  • 自己进入发送队列,休眠等待。
  • 把自己包装成sudog
  • sudog放入sendq队列
  • 休眠并解锁
  • 被唤醒后,数据已经被取走,维护其他数据。

总结

  • 编译阶段,会把<-转化为runtime.chansend1()
    1. 直接发送时,将数据拷贝到目标变量。
    1. 放入缓存时,将数据放入环形缓存,成功返回。
    1. 休眠等待时,将自己包装成sudog后放入sendq,休眠。

Channel接收数据的底层原理是什么?

<-c关键字

  • <-c 关键字是一个语法糖
  • 编译时, i <- c转化为runtime.chanrecv1()
  • 编译阶段,i,ok <-c 转化为runtime.chanrecv2()
  • 最后会调用chanrecv()方法。
    在这里插入图片描述
有等待的G,从G接收
  • 接收数据前,已经有G在休眠等待发送。
  • 而且这个Channel没有缓存。
  • 将数据直接从G拷贝过来,唤醒G。
  • 判断有G在发送队列等待,进入recv()
  • 判断此Channel无缓存。
  • 直接从等待的G中取走数据,唤醒G。
有等待的G,从缓存接收
  • 接收数据前,已经有G在休眠等待发送
  • 而且这个Channel有缓存
  • 从缓存取走一个数据
  • 将休眠G的数据放进缓存,唤醒G。
  • 判断有G在发送队列等待,进入recv()
  • 判断此Channel有缓存
  • 从缓存中取走一个数据
  • 将G的数据放入缓存,唤醒G.
从缓存中接收
  • 没有G在休眠等待发送,但是缓存有内容
  • 直接从缓存取走数据
  • 判断没有G在发送队列等待
  • 判断此Channel有缓存
  • 从缓存中取走一个数据
阻塞接收
  • 没有G在休眠等待,而且没有缓存或缓存为空。
  • 自己进入接收队列,休眠等待。
  • 判断没有G在发送队列等待
  • 判断此Channel无缓存
  • 将自己包装成sudog
  • sudog放入等待队列,休眠。
  • 唤醒时,发送的G已经把数据拷贝到位。

非阻塞的Channel怎么做?

func main() {
	ch1 := make(chan int, 5)
	ch2 := make(chan int)

	select {
	case <-ch1:
		fmt.Println("葛诗颖")
	case ch2 <- 1:
		fmt.Println("诗诗")
	default:
		fmt.Println("葛诗颖在刷抖音")
	}
}

运行结果

葛诗颖在刷抖音

Process finished with the exit code 0

select 原理

  • 在编译后的汇编语言中 同时存在接收、发送、默认路径。
  • 首先查看是否有可以即时执行的case。
  • 没有的话,有default,执行default。
  • 没有default,把自己注册在所有的Channel中,休眠等待。

timer

  • timer可以提供一个Channel,定时塞入数据。
  • 14
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值