本文共 3515 字,大约阅读时间需要 11 分钟。
Do not communicate by sharing memory; instead, share memory by communicating.
这种方式的优点是通过提供原子的通信原语,避免了竞态情形(race condition)下复杂的锁机制。
type hchan struct { qcount uint // 已经接收但还没被取走的元素的个数,函数 len 返回这个字段的值; dataqsiz uint // 队列buffer的大小,cap函数可以返回这个字段的值以及队列buffer的指针,是一个定长的环形数组; buf unsafe.Pointer // 缓冲chan的循环队列的指针,非缓冲为自己的地址 elemsize uint16 // chan中元素的大小 closed uint32 // 是否已close,未关闭=0 elemtype *_type // chan中元素类型 sendx uint // send在buffer中的索引 recvx uint // recv在buffer中的索引 recvq waitq // receiver的等待队列 sendq waitq // sender的等待队列 lock mutex // 互斥锁}
在 channel 的内部实现中(具体定义在 $GOROOT/src/runtime/chan.go
里),维护了 3 个队列:
初始化 hchan 简单的分为三种情况:(为啥?)
switch {// no buffer 的场景,这种 channel 可以看成 pipecase mem == 0: c = (*hchan)(mallocgc(hchanSize, nil, true)) c.buf = c.raceaddr()// 元素不含指针,分配一个连续大内存块;case elem.ptrdata == 0: c = (*hchan)(mallocgc(hchanSize+mem, nil, true)) c.buf = add(unsafe.Pointer(c), hchanSize)// 元素含有指针,hchan 结构体和 buffer 内存块单独分配;default: c = new(hchan) c.buf = mallocgc(mem, elem, true)}
block=true
): chansend1
、selectnbsend
block=false
):selectnbrecv
、 selectnbrecv2
block=true
): chanrecv1
、chanrecv2
block=false
):selectnbrecv
、 selectnbrecv2
v := <-c// ok is false when ch is closed。非阻塞。v, ok := <-c //读取一个已关闭的 channel 时,总是能读取到对应类型的零值,为了和读取非空未关闭 channel 的行为区别,可以使用两个接收值
selectnbsend
selectnbrecv
selectnbrecv2
(非阻塞,失败为default分支)chanrecv2
当协程尝试从未关闭的 channel 中读取数据时,内部的操作如下:
当协程尝试往未关闭的 channel 中写入数据时,内部的操作如下:
当关闭 non-nil channel 时,内部的操作如下:
futures/promises
、条件变量(condition variable)
、广播通知
、信号量
、互斥量
GC
回收。关闭 channel 一般是用来通知其他协程某个任务已经完成了。golang 也没有直接提供判断 channel 是否已经关闭的接口。所以使用的时候要特别注意,不要让协程阻塞在 channel 上,这种情况很难检测到,而且会造成 channel 和阻塞在 channel 的协程占有的资源无法被 GC 清理最终导致内存泄露。操作 | nil channel | closed channel | not-closed non-nil channel |
---|---|---|---|
close | panic | panic | 成功 close |
写 ch <- | 一直阻塞 | panic | 阻塞或成功写入数据 |
读 <- ch | 一直阻塞 | 读取对应类型零值 | 阻塞或成功读取数据 |
http://www.usingcsp.com/
https://go101.org/article/channel.html https://go101.org/article/channel-use-cases.html https://go101.org/article/channel-closing.html https://www.jianshu.com/p/819aa9b9af86cat <
转载地址:http://xviti.baihongyu.com/