通道

99 阅读1分钟

原理

channel用于多个goroutine之间传递数据,且保证整个过程的并发安全性。

channel是Go特有一种数据结构,可以理解为一个管道。推荐使用通信的方式来共享内存。

Go面试题(五):图解 Golang Channel 的底层原理 - 掘金 (juejin.cn)

当channel中的缓存满了之后会发生什么呢?

0ad2bc00a330431ba9a4c828b8d04c8c_tplv-k3u1fbpfcp-zoom-in-crop-mark_3024_0_0_0.webp 当G1向buf已经满了的ch发送数据的时候,检测到hchan的buf已经满了,会通知p,p会将G1的状态设置为waiting, 并移除与线程M的联系,然后从P的runqueue中选择一个goroutine在线程M中执行,此时G1就是阻塞状态,但是不是操作系统的线程阻塞,所以这个时候只用消耗少量的资源。 sendq表示那些堵塞的gorutine,当ch中的数据被读取时,g1有会回到p的本队队列里去

  • Channel为什么是线程安全的?

    在对buf中的数据进行入队和出队操作时,为当前chnnel使用了互斥锁,防止多个线程并发修改数据

channel底层数据结构

0.png

a20f10cd62284684963a3a1edd44a90e_tplv-k3u1fbpfcp-zoom-in-crop-mark_3024_0_0_0.webp image.png

image.png

创建

  1. make(chan int) //无缓冲
  2. make(chan int,10)//有缓冲 创建的是一个指针

向channel发送数据过程

  1. 发送操作转为chansend函数

关闭

image.png

向 channel 发送元素的就是 sender,因此 sender 可以决定何时不发送数据,并且关闭 channel。 但是如果有多个 sender,某个 sender 同样没法确定其他 sender 的情况,这时也不能贸然关闭 channel。

don’t close (or send values to) closed channels.

image.png

就是说 channel 的发送和接收操作本质上都是 “值的拷贝”,

泄露

image.png