读draveness关于chan的介绍后的总结
读draveness关于chan的介绍后的总结及疑问
chan 实现了go提出的通过通信来共享内存的效果
-
无缓冲区时则为同步
chan 的接收及发送
- recvq 是阻塞的接收方队列,即x = <-ch里当ch里面没有数据给x了,就会把x所在的goroutine记录在recvq里面等待数据
- sendq 是阻塞了的发送方队列,即ch <- i里当ch的缓冲区满了,就会把数据先放到sendq里面去,等到缓冲区里面被消费了一条就从sendq里面拷贝一条到缓冲区去,然后释放被拷贝的sendq对应的goroutine
- 如果存在阻塞的接收者(recvq),发送数据是不会先存到缓冲区(即,不会经过chan),而是直接将值拷贝给x = <-ch中的x对应的地址,流程是,先判断chan的recvq是否为空,不为空则直接把值拷贝到recvx对应的goroutine
- 所以 recvq和sendq至多有一个里面有内容
对于带缓冲区和不带缓冲区的chan,go处理上的区别在于,有缓冲区的,在创建chan时,会额外开内存空间来存放缓冲区
chan关闭后,缓冲区中的数据还能被读取的
切记应该在写入ch的goroutine进行关闭操作,否则会有意料之外的panic
chan的缓冲区
- chan的缓冲区是环形的,即发送角标(sendx )或者写入角标(recvx )到了等于缓冲区长度(dataqsiz)后会跳转到头部(角标变为0)
- 当发送角标==写入角标时证明已经消费完了
- 当缓冲区的元素个数(qcount )==缓冲区可容纳元素个数(dataqsiz )时证明缓冲区就满了
本作品采用《CC 协议》,转载必须注明作者和本文链接