如果我是面试官,让你说说go chan的设计原理你会怎么说呢?
我理解go在协程的通信中是花了大心思的,他并没有走相对老套的通信方式(无名管道,有名管道,共享内存,套接字,信号量),而是提出了新的思想,不要通过共享内存的方式进行通信,而是应该通过通信的方式共享内存,这句话很拗口,我并不想强调它。记住他这个CSP<(通信顺序进程(Communicating sequential processes)>新思想即可。
协程主要的数据结构有哪些?
- 最基础的,chan分为有缓冲和无缓冲你知道的吧。既然有缓冲,肯定得有个字段来记录你申请的这个chan 的cap是多大吧,他不可能无限大。所以应该有个容量的记录字段吧**dataqsiz **
- 他肯定有个字段来记录目前chan里面有多少个元素了qcount
- 我们是不是应该考虑资源的重复利用?重复使用可以减少系统调用,这里chan使用的是环形队列 ****
- 既然有了环形队列自然而然的就应该想到有两个指针,表示消息当前生产者写到哪个位置了sendx,消费者读到哪个位置了recvx
- 申请chan的时候你还记得必须有消息类型吗?是的,同样还得有个字段记录消息类型**elemtype **
- chan 是一个线程安全的通信媒介怎么可能没有锁呢?lock 之前我说到有锁这个事情的时候他笑话我说,呵呵,chan其实是没有锁的 目前通过 CAS 实现的无锁 Channel 没有提供先进先出的特性,所以该提案暂时也被搁浅了,所以chan是有锁的实现,请参考Dmitry Vyukov. Dec, 2016. “algorithm does not apply per se
chan的基本框架已经出来了,能说到这里基本上差不多了吧,接下来我们看下源码的定义
go chan struct
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
}
type waitq struct {
first *sudog
last *sudog
}
提纲挈领的说一些自己思考chan的思路,更有助于记住这些原理