channel使用
介绍
- 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的特性
- 给⼀个 nil channel 发送数据,造成永远阻塞
- 从⼀个 nil channel 接收数据,造成永远阻塞
- 给⼀个已经关闭的 channel 发送数据,引起 panic
- 从⼀个已经关闭的 channel 接收数据,如果缓冲区中为空,则返回⼀个零值
- ⽆缓冲的 channel 是同步的,⽽有缓冲的 channel 是⾮同步的
- 关闭⼀个 nil channel 将会发⽣ panic
channel的ring buffer实现
channel 中使⽤了 ring buffer(环形缓冲区)来缓存写⼊的数据。ring buffer 有很多好处,⽽且⾮常适合⽤来实现 FIFO 式的固定⻓度队列。在 channel 中,ring buffer 的实现如下:
hchan 中有两个与 buffer 相关的变量:recvx 和 sendx。其中 sendx 表示buffer 中可写的 index,recvx 表示 buffer 中可读的 index。从 recvx 到 sendx 之间的元素,表示已正常存放⼊ buffer 中的数据。
我们可以直接使⽤ buf[recvx]来读取到队列的第⼀个元素,使⽤ buf[sendx]= x 来将元素放到队尾。
无缓冲channel和有缓冲channel的demo
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 igl1t's blog!