golang channel几点总结

时间:2023-03-10 03:24:21
golang channel几点总结

golang提倡使用通讯来共享数据,而不是通过共享数据来通讯。channel就是golang这种方式的体现。

Channel

在golang中有两种channel:带缓存的和不带缓存。

  • 带缓存的channel,也就是可以异步收发的。
  • 不带缓存的channel,也就是同步收发的。

发送:

• 向 nil channel 发送数据,阻塞。

• 向 closed channel 发送数据,出错。

• 同步发送: 如有接收者,交换数据。否则排队、阻塞。

• 异步发送: 如有空槽,拷⻉贝数据到缓冲区。否则排队、阻塞。

接收:

• 从 nil channel 接收数据,阻塞。

• 从 closed channel 接收数据,返回已有数据或零值。

• 同步接收: 如有发送者,交换数据。否则排队、阻塞。

• 异步接收: 如有缓冲项,拷⻉贝数据。否则排队、阻塞。

底层实现

使用channel时,多个goroutine并发发送和接收,却无需加锁,为什么呢?

其实,是由底channel层实现做支撑的。

channel的具体定义参见/usr/local/go/src/runtime/chan.go

type hchan struct {
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
elemsize uint16
closed uint32
elemtype *_type // element type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters // lock protects all fields in hchan, as well as several
// fields in sudogs blocked on this channel.
//
// Do not change another G's status while holding this lock
// (in particular, do not ready a G), as this can deadlock
// with stack shrinking.
lock mutex
}

可以看到,有lock字段,在使用channel进行发送和接收的时候,会进行加锁保护。

参考

雨痕《Go学习笔记 第四版》