BIO,NIO,AIO 的区别
因此卡住不动了只是同步请求的一个副作用,并不能用它来定义同步请求,那该如何定义呢?
二、同步和异步
所谓同步,指的是协同步调。既然叫协同,所以至少要有 2 个以上的事物存在。协同的结果就是:
多个事物不能同时进行,必须一个一个的来,上一个事物结束后,下一个事物才开始。
那当一个事物正在进行时,其它事物都在干嘛呢?
严格来讲这个并没有要求,但一般都是处于一种“等待”的状态,因为通常后面事物的正常进行都需要依赖前面事物的结果或前面事物正在使用的资源。
因此,可以认为,同步更希望关注的是从宏观整体来看,多个事物是一种逐个逐个的串行化关系,绝对不会出现交叉的情况。
所以,自然也不太会去关注某个瞬间某个具体事物是处于一个什么状态。
把这个理论应用的出神入化的非“排队”莫属。凡是在资源少需求多的场景下都会用到排队。
比如排队买火车票这件事:
其实售票大厅更在意的是旅客一个一个的到窗口去买票,因为一次只能卖一张票。
即使大家一窝蜂的都围上去,还是一次只能卖一张票,何必呢?挤在一起又不安全。
只是有些人素质太差,非要往上挤,售票大厅迫不得已,采用排队这种形式来达到自己的目的,即一个一个的买票。
至于每个旅客排队时的状态,是看手机呀还是说话呀,根本不用去在意。
除了这种由于资源导致的同步外,还存在一种由于逻辑上的先后顺序导致的同步。
比如,先更 《一线大厂 Java 面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 新代码,然后再编译,接着再打包。这些操作由于后一步要使用上一步的结果,所以只能按照这种顺序一个一个的执行。
关于同步还需知道两个小的点:
一是范围,并不需要在全局范围内都去同步,只需要在某些关键的点执行同步即可。
比如食堂只有一个卖饭窗口,肯定是同步的,一个人买完,下一个人再买。但吃饭的时候也是一个人吃完,下一个人才开始吃吗?当然不是啦。
二是粒度,并不是只有大粒度的事物才有同步,小粒度的事物也有同步。
只不过小粒度的事物同步通常是天然支持的,而大粒度的事物同步往往需要手工处理。
比如两个线程的同步就需要手工处理,但一个线程里的两个语句天然就是同步的。
所谓异步,就是步调各异。既然是各异,那就是都不相同。所以结果就是:
多个事物可以你进行你的、我进行我的,谁都不用管谁,所有的事物都在同时进行中。
一言以蔽之,同步就是多个事物不能同时开工,异步就是多个事物可以同时开工。
注:一定要去体会“多个事物”,多个线程是多个事物,多个方法是多个事物,多个语句是多个事物,多个 CPU 指令是多个事物。等等等等。
三、阻塞和非阻塞
所谓阻塞,指的是阻碍堵塞。它的本意可以理解为由于遇到了障碍而造成的动弹不得。
所谓非阻塞,自然是和阻塞相对,可以理解为由于没有遇到障碍而继续畅通无阻。
对这两个词最好的诠释就是,当今中国一大交通难题,堵车:
汽车可以正常通行时,就是非阻塞。一旦堵上了,全部趴窝,一动不动,就是阻塞。
因此阻塞关注的是不能动,非阻塞关注的是可以动。
不能动的结果就是只能等待,可以动的结果就是继续前行。
因此和阻塞搭配的词一定是等待,和非阻塞搭配的词一定是进行。
回到程序里,阻塞同样意味着停下来等待,非阻塞表明可以继续向下执行。
四、阻塞和等待
等待只是阻塞的一个副作用而已,表明随着时间的流逝,没有任何有意义的事物发生或进行。
阻塞的真正含义是你关心的事物由于某些原因无法继续进行,因此让你等待。但没必要干等,你可以做一些其它无关的事物,因为这并不影响你对相关事物的等待。
在堵车时,你可以干等。也可以玩手机、和别人聊天,或者打牌、甚至先去吃饭都行。因为这些事物并不影响你对堵车的等待。不过你的车必须呆在原地。
在计算机里,是没有人这么灵活的,一般在阻塞时,选在干等,因为这最容易实现,只需要挂起线程,让出 CPU 即可。在条件满足时,会重新调度该线程。
五、两两组合
所谓同步/异步,关注的是能不能同时开工。
所谓阻塞/非阻塞,关注的是能不能动。
通过推理进行组合:
同步阻塞,不能同时开工,也不能动。只有一条小道,一次只能过一辆车,可悲的是还 TMD 的堵上了。
同步非阻塞,不能同时开工,但可以动。只有一条小道,一次只能过一辆车,幸运的是可以正常通行。
异步阻塞,可以同时开工,但不可以动。有多条路,每条路都可以跑车,可气的是全都 TMD 的堵上了。
异步非阻塞,可以工时开工,也可以动。有多条路,每条路都可以跑车,很爽的是全都可以正常通行。
是不是很容易理解啊。其实它们的关注点是不同的,只要搞明白了这点,组合起来也不是事儿。
回到程序里,把它们和线程关联起来:
同步阻塞,相当于一个线程在等待。
同步非阻塞,相当于一个线程在正常运行。
异步阻塞,相当于多个线程都在等待。
异步非阻塞,相当于多个线程都在正常运行。
六、I/O
IO 指的就是读入/写出数据的过程,和等待读入/写出数据的过程。一旦拿到数据后就变成了数据操作了,就不是 IO 了。
拿网络 IO 来说,等待的过程就是数据从网络到网卡再到内核空间。读写的过程就是内核空间和用户空间的相互拷贝。
评论