彻底搞懂Channel原理之二

开发 前端
我们提到,对channel的操作,本质上就是对hchan里字段的操作。因为在操作的过程中使用了互斥锁,所以保证了channel的并发安全。

[[427995]]

本文转载自微信公众号「吴亲强的深夜食堂」,作者吴亲库里。转载本文请联系吴亲强的深夜食堂公众号。

上一篇文章主要介绍channel运行时是通过hchan表示的,也简单说明了hchan各个字段的含义。

我们提到,对channel的操作,本质上就是对hchan里字段的操作。因为在操作的过程中使用了互斥锁,所以保证了channel的并发安全。

这篇文章主要通过现实生活的一些例子来说明channel的一些原理,当然还是不会涉及过多源码。

无缓冲

我们都知道,channel分为无缓冲和缓冲。这两者最大的区别是什么?

我们用一个现实生活的快递例子来说明。

上面场景是快递员在等小库,当然反过来小库也可能在等快递员。

如果没有快递柜,快递员在送快递的过程中,如果家里没人,他就得在那等着,等着有人来签收快递,他才送货结束。

客户在快递员到来之前,他也不能离开家,不然快递来了没人收,所以他也得等到快递员上门,签字收了快递,他才算收货结束。

当然,客户不止有这家快递,如果快递员A在等的时候又来一个快递员B给他送货。这个快递员B不仅得等着,还得排队。等到客户到家后,肯定是先签收A的快递,然后再签收B的快递。

对应到无缓冲channel,

发送数据的时候,如果没有对应的接收者ready,那么发送者就进入到等待发送队列中,等待有对应的接收者唤醒它。

接收数据的时候,如果没有对应的发送者ready,那么接收者就进入到等待接收队列中,等待有对应的发送者唤醒它。

还记得上一篇文章我们介绍过hchan的结构吗。

其中recvq表示等待接收消息的队列,sendq表示等待发送消息的队列。

我们来看waitq。

本质上waitq就是一个链表,更确切的说是一个双向循环的链表。其中waitq记录了链表的头尾,sudog记录了当前等待者的上一个等待者(prev)和下一个等待者(next)。

这就好像小库在签收完A的快递后喊,下一个是谁啊?

A会说:我的下一个是B。

B会说:是我。我记得我上一个是A,目前我没有下一个,所以我是最后一个。

缓冲

看完了无缓冲队列,我们再来看缓冲队列。还是用上面的故事,

只要快递柜有空闲柜子,快递员就可以直接把快递放到柜子里,让客户自己去柜子拿。如果发送没有空闲的柜子,那就只能等,等到别人告诉我有空闲柜子,我再把快递放到空出来的柜子里。

对应到缓冲channel,上面的快递柜,就是缓冲channel中存储数据的buffer。

对于发送者来说:只要缓冲区未满,发送者就可以继续发送数据存放在缓冲区。一旦缓冲区满了,发送者就只能进入到等待发送队列中,等待有对应的接收者唤醒它,然后它再把数据放入到刚刚被取走数据的位置。

对于接收者来说:只要缓冲区不为空,接收者就可以继续接收数据。一旦缓冲区空了,那么接收者就只能进入到等待接收队列中,等待有对应的发送者唤醒它。

上面还有什么问题吗?还真有。

我们取快递的时候,你一定会按照快递放入到快递柜的先后顺序取快递吗?咋么可能。

但是在channel中,是会保证消息的先进先出(FIFO)关系的。至于咋么保证的,我们终结篇解析代码细节的时候再说。

总结 

这篇文章主要通过一个快递的例子来介绍channel操作的原理。下一篇我们介绍channel针对上述处理的细节逻辑。

 

责任编辑:武晓燕 来源: 吴亲强的深夜食堂
相关推荐

2021-10-09 19:05:06

channelGo原理

2023-10-18 10:55:55

HashMap

2023-05-29 08:12:38

2021-07-08 10:08:03

DvaJS前端Dva

2022-04-24 11:06:54

SpringBootjar代码

2022-08-26 13:24:03

version源码sources

2021-07-16 11:35:20

Java线程池代码

2020-04-28 22:12:30

Nginx正向代理反向代理

2021-08-18 23:10:56

setState代码性能

2020-10-14 08:50:38

搞懂 Netty 线程

2017-12-05 17:44:31

机器学习CNN卷积层

2024-01-03 13:39:00

JS,Javascrip算法

2019-07-23 08:55:46

Base64编码底层

2024-03-08 10:38:07

Vue响应式数据

2021-10-15 08:32:03

RocketMQ数据结构架构

2023-09-28 08:15:05

SpringBean加载

2021-12-29 17:29:07

KubernetesEvents集群

2021-04-06 08:20:24

二叉搜索树数据结构算法

2023-03-09 09:06:13

ChanneGo开发

2021-07-21 05:24:32

EventBus3.0Android单例模式
点赞
收藏

51CTO技术栈公众号