线程安全吗?
Channel,发送一个数据到Channel 和 从Channel接收一个数据 都是 原子性的。而且Go的设计思想就是:不要通过共享内存来通信,而是通过通信来共享内存,前者就是传统的加锁,后者就是Channel。也就是说,设计Channel的主要目的就是在多任务间传递数据的,这当然是安全的
channel内部维护了一个互斥锁,来保证线程安全**
无缓存和有缓存区别
无缓存:表示发送者必须等待数据被接收者接收才会继续发送到channel中。
有缓存:设置了缓存区大小,发送者不必等待接收者就绪,而是直接无脑往channel中丢数据,直到数据满到初始创建设定的大小为止
channel代码实现
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 mutex // 互斥锁
}
实现
- buf是有缓冲的channel所特有的结构,用来存储缓存数据。是个循环链表
- sendx和recvx用于记录buf这个循环链表中的发送或者接收的index
- lock是个互斥锁
- recvq和sendq分别是接收(<-channel)或者发送(channel <- xxx)的goroutine抽象出来的结构体(sudog)的队列。是个双向链表
简记
一个存储缓存的循环链表,两个index,一个用于记录发送;一个用于接受,两个双向链表存储收到和发送的数据,一个互斥锁。