同步异步,阻塞非阻塞

2019-06-13  本文已影响0人  huapro

“阻塞”与"非阻塞"与"同步"与“异步"不能简单的从字面理解,提供一个从分布式系统角度的回答。
1.同步与异步
同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)
所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不返回。但是一旦调用返回,就得到返回值了。
换句话说,就是由调用者主动等待这个调用的结果。

而异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。

典型的异步编程模型比如Node.js

举个通俗的例子:
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。

2. 阻塞与非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.

阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

还是上面的例子,
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。

如果是关心阻塞 IO/ 异步 IO, 参考 Unix Network Programming View Book

--

还是2014年写的以解释概念为主,主要是同步异步 阻塞和非阻塞会被用在不同层面上,可能会有不准确的地方,并没有针对 阻塞 IO/ 异步 IO 等进行讨论,大家可以后续看看这两个回答:

怎样理解阻塞非阻塞与同步异步的区别?

怎样理解阻塞非阻塞与同步异步的区别?

(1)同步和异步

​ 同步和异步描述的是一种消息通知的机制,主动等待消息返回还是被动接受消息。同步io指的是调用方通过主动等待获取调用返回的结果来获取消息通知,而异步io指的是被调用方通过某种方式(如,回调函数)来通知调用方获取消息。

(2)阻塞非阻塞

阻塞和非阻塞描述的是调用方在获取消息过程中的状态,阻塞等待还是立刻返回。阻塞io指的是调用方在获取消息的过程中会挂起阻塞,知道获取到消息,而非阻塞io指的是调用方在获取io的过程中会立刻返回而不进行挂起。

image

重新认识同步与异步,阻塞和非阻塞的概念

前言

在实际的开发中,我们经常会听到同步,异步,阻塞,非阻塞这些编程概念,每次遇到的时候都会蒙圈,然后就各种查网上似是而非的资料,结果越查越迷糊,大部分文章都千篇一律,没有说到本质上的区别,所以下次再碰到这些概念,印象还是比较模糊,尤其是在一些场景下同步与阻塞,异步与非阻塞感觉没啥区别,但其实这四个术语描述的事物还真不是一回事。

下面我们来慢慢探讨他们之间的区别与联系,在这之前,我们还会经常看到下面的组合术语:

(一)同步+阻塞

(二)同步+非阻塞

(三)异步+阻塞

(四)异步+非阻塞

在当什么是同步和异步,阻塞与非阻塞的概念还没弄清楚之前,更别提上面这些组合术语了,只会让你更加困惑。

关于同步和异步

同步和异步其实指的是,请求发起方对消息结果的获取是主动发起的,还是等被动通知的。如果是请求方主动发起的,一直在等待应答结果(同步阻塞),或者可以先去处理其他的事情,但要不断轮询查看发起的请求是否有应答结果(同步非阻塞 )因为不管如何都要发起方主动获取消息结果,所以形式上还是同步操作。如果是由服务方通知的,也就是请求方发出请求后,要么在一直等待通知(异步阻塞),要么就先去干自己的事了(异步非阻塞),当事情处理完成之后,服务方会主动通知请求方,它的请求已经完成,这就是异步。异步通知的方式一般是通过状态改变,消息通知,或者回调函数来完成,大多数时候采用的都是回调函数。

关于阻塞和非阻塞

阻塞和非阻塞在计算机的世界里面,通常指的是针对IO的操作,如网络IO和磁盘IO等。那么什么是阻塞和非阻塞呢?简单的说就是我们调用了一个函数之后,在等待这个函数返回结果之前,当前的线程是处于挂起状态,还是运行状态,如果是挂起状态,就意味着当前线程什么都不能干,就等着获取结果,这就叫同步阻塞,如果仍然是运行状态,就意味当前线程是可以的继续处理其他任务,但要时不时的去看下是否有结果了,这就是同步非阻塞。

实际生活场景

同步,异步,阻塞和非阻塞,会组合成上面提到过的四种结果:

(一)同步+阻塞

(二)同步+非阻塞

(三)异步+阻塞

(四)异步+非阻塞

举个例子,比如我们去照相馆拍照,拍完照片之后,商家说需要30分钟左右才能洗出来照片,

*这个时候如果我们一直在店里面啥都不干,一直等待商家面前等待它洗完照片,这个过程就叫同步阻塞。

当然大部分人很少这么干,更多的是大家拿起手机开始看电视,看一会就会问老板洗完没,老板说没洗完,然后我们接着看,再过一会接着问,直到照片洗完,这个过程就叫同步非阻塞。

因为店里生意太好了,越来越多的人过来拍,店里面快没地方坐了,老板说你把你手机号留下,我一会洗好了就打电话告诉你过来取,然后你去外面找了一个长凳开始躺着睡觉等待老板打电话,啥不都干,这个过程就叫异步阻塞。

当然实际情况是,大家可能会直接先去逛街或者吃饭做其他的活动,这样以来两不耽误,这个过程就叫异步非阻塞

总结

本文主要介绍了同步,异步,阻塞和非阻塞的相关概念和例子,从上面的描述中我们其实能够看到阻塞和非阻塞通常是指客户端在发出请求后,在服务端处理这个请求的过程中,客户端本身是否直接挂起等待结果,还是继续做其他的任务。而异步和同步,则是对于请求结果的获取是客户端主动等待获取,还是由服务端来通知消息结果。从这一点来看同步和阻塞其实描述的两个不同角度的事情,阻塞和非阻塞指的一个是客户端等待消息处理时的本身的状态,是挂起还是继续干别的。同步和异步指的对于消息结果的获取是客户端主动获取,还是由服务端间接推送。记住这两点关键的区别将有助于我们更好的区分和理解它们。

AIO 是彻底的异步通信。
NIO 是同步非阻塞通信。
有一个经典的举例。烧开水。
假设有这么一个场景,有一排水壶(客户)在烧水。

AIO的做法是,每个水壶上装一个开关,当水开了以后会提醒对应的线程去处理。
NIO的做法是,叫一个线程不停的循环观察每一个水壶,根据每个水壶当前的状态去处理。
BIO的做法是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。

可以看出AIO是最聪明省力,NIO相对省力,叫一个人就能看所有的壶,BIO最愚蠢,劳动力低下。

在处理 IO 的时候,阻塞和非阻塞都是同步 IO。
只有使用了特殊的 API 才是异步 IO。

7d3eb389b7724878bd7e12ebc6dbcdb5_720w.jpg
上一篇下一篇

猜你喜欢

热点阅读