channel

439 词

介绍

  • Go语⾔中,不要通过共享内存来通信,⽽要通过通信来实现内存共享。Go的 CSP(Communicating Sequential Process)并发模型,中⽂可以叫做通信顺序进程,是通过 goroutine 和 channel 来实现的。所以 channel 收发遵循先进先出 FIFO,分为有缓存和⽆缓存,channel 中⼤致有 buffer(当缓冲区⼤⼩部位0 时, 是个 ring buffer)、sendx 和 recvx 收发的位置(ring buffer 记录实现)、sendq、recvq 当前 channel 因为缓冲区不⾜⽽阻塞的队列、使⽤双向链表存储、还有⼀个 mutex 锁控制并发、其他原属等。
  • 向channel写入数据和从channel里面读数据都是原子性的,所以channel是并发安全的。

channel的特性

  1. 给⼀个 nil channel 发送数据,造成永远阻塞
  2. 从⼀个 nil channel 接收数据,造成永远阻塞
  3. 给⼀个已经关闭的 channel 发送数据,引起 panic
  4. 从⼀个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回⼀个零值
  5. ⽆缓冲的 channel 是同步的,⽽有缓冲的 channel 是⾮同步的
  6. 关闭⼀个 nil channel 将会发⽣ panic

channel的ring buffer实现

channel 中使⽤了 ring buffer(环形缓冲区)来缓存写⼊的数据。ring buffer 有很多好处,⽽且⾮常适合⽤来实现 FIFO 式的固定⻓度队列。在 channel 中,ring buffer 的实现如下:
image.png
hchan 中有两个与 buffer 相关的变量:recvx 和 sendx。其中 sendx 表示buffer 中可写的 index,recvx 表示 buffer 中可读的 index。从 recvx 到 sendx 之间的元素,表示已正常存放⼊ buffer 中的数据。
我们可以直接使⽤ buf[recvx]来读取到队列的第⼀个元素,使⽤ buf[sendx]= x 来将元素放到队尾。

无缓冲channel和有缓冲channel的demo

image.png
image.png

留言