的原理本文转载自微信公众号《吴沁强的深夜食堂》,作者吴沁库里。转载本文请联系吴勤强深夜食堂公众号。上一篇文章主要介绍了channelruntime用hchan表示,也简单解释了hchan各个字段的含义。我们提到了对channel的操作本质上就是对hchan中字段的操作。由于在运行过程中使用了互斥量,保证了通道的并发安全。本文主要通过一些现实生活中的例子来说明channel的一些原理,当然不会涉及太多的源代码。众所周知unbuffered,channel分为unbuffered和buffered。两者最大的区别是什么?让我们用一个现实生活中的快递员例子来说明。上图,快递员正在等小酷。当然,小酷也可能在等快递。如果没有快递柜,快递员在派送快递的过程中,如果家里没人,就得在那里等着,等着有人签收快递,他才完成派送。客户在快递员到达之前不能离开家,否则没人会收快递,所以他必须等到快递员上门签收快递后,才算收到货。当然,客户不只有这个快递员,如果快递员A在等,另一个快递员B会给他送货。这个快递B不仅要等,还要排队。客户到家后,必须先签收A的快递,再签收B的快递。对应unbufferedchannel,在发送数据的时候,如果没有对应的receiver准备好,那么sender就会进入等待队列,等待对应的receiver将其唤醒。接收数据时,如果没有对应的sender就绪,则receiver会进入等待队列,等待对应的sender将其唤醒。还记得我们上一篇介绍的hchan的结构吗。其中recvq表示等待接收消息的队列,sendq表示等待发送消息的队列。让我们看看waitq。waitq本质上是一个链表,更准确的说是一个双向循环链表。其中waitq记录了链表的头和尾,sudog记录了当前等待者的上一个等待者(prev)和下一个等待者(next)。就好像小酷签完A的快递大喊,下一个是谁?A会说:我的下一个是B。B会说:是我。我记得我的最后一个是A,目前我没有下一个,所以我是最后一个。缓冲读完无缓冲队列,让我们看看有缓冲队列。还是用上面的故事,只要快递柜里有空闲的柜子,快递员就可以直接把快递放在柜子里,让客户去柜子里取。如果没有免费的柜子派送,我只能等到有人告诉我有空柜子的时候,我才会把快递放在空柜子里。对应缓冲通道,上面的快递柜就是缓冲区,用于在缓冲通道中存储数据。对于发送方:只要缓冲区没有满,发送方就可以继续发送数据,并将数据存放在缓冲区中。一旦缓冲区满了,发送端就只能进入等待队列,等待相应的接收端将其唤醒,然后将数据放入刚刚取走数据的位置。对于接收方:只要缓冲区不为空,接收方就可以继续接收数据。一旦缓冲区为空,接收方只能进入等待队列,等待相应的发送方将其唤醒。以上有没有问题?有。我们取快递的时候,你一定会按照快递放入快递柜的顺序取快递吗?这怎么可能?但是在通道中,保证了消息的先进先出(FIFO)关系。至于如何保证,我们在最后一章分析代码细节的时候再说。小结本文主要通过一个快递的例子来介绍渠道运作的原理。在下一篇文章中,我们将介绍通道对上述处理的详细逻辑。
