彻底理解同步与异步,阻塞和非阻塞概念
提示:本文章旨在帮助大家理清思路和理解各名词的概念,帮助大家日后的学习
前言
在实际的开发中,我们经常会听到同步,异步,阻塞,非阻塞这些编程概念,每次遇到的时候都会蒙圈,然后就各种查网上似是而非的资料,结果越查越迷糊,大部分文章都千篇一律,没有说到本质上的区别,所以看了就忘根本记不住,印象还是比较模糊,尤其是在一些场景下同步与阻塞,异步与非阻塞感觉没啥区别,但其实这四个术语描述的事物还真不是一回事。本文结合自己的操作和对先前文章的理解,先解释概念,然后再举例让大家记得更加清晰。下面我们来慢慢探讨他们之间的区别与联系。
一、同步和异步
很多人的第一反应就是“同”和“异”的区别,何为同?何为异?我相信大家都有清晰的认识。但是后面加一个“步”,两个词语意思又变了味道。
在编程语言中,同步和异步描述的是消息通信的机制。
1.同步:
当一个request发送出去以后,会得到一个response,这整个过程就是一个同步调用的过程。哪怕response为空,但是针对这一次请求而言就是一个同步的调用。
2.异步:
当一个request发送出去以后,没有得到response的返回,而是通过后面的callback、状态或者通知的方式获得结果。这就是一个异步调用。可以这么理解,对于异步请求分两步:
- 调用方发送request没有返回对应的response(可能是一个空response)。
- 服务提供方将response处理完成以后通过callback的方式通知调用方。
对于1而言是同步操作(调用方请求服务方),对于2而言也是同步操作(服务方回掉调用方)。从请求的目的(调用方发送一个request,希望获得对应的response)来看,这两个步骤拆分开来没有任何意义,需要结合起来看,而这整个过程就是一次异步请求。异步请求有一个最典型的特点:需要callback、状态或者通知的方式来告知调用方结果。
哈哈,是不是听起来还有一点迷糊?别急我再跟你们聊聊,看完下面这个你们应该就会明白。
同步和异步其实指的是,请求发起方对消息结果的获取是主动发起的,还是等被动通知的。
如果是请求方主动发起的,一直在等待应答结果(同步阻塞),或者可以先去处理其他的事情,但要不断轮询查看发起的请求是否有应答结果(同步非阻塞 ),因为不管如何都要发起方主动获取消息结果,所以形式上还是同步操作。但是中间夹杂了阻塞和非阻塞的操作。
如果是由服务方通知的,也就是请求方发出请求后,要么在一直等待通知(异步阻塞),要么就先去干自己的事了(异步非阻塞),当事情处理完成之后,服务方会主动通知请求方,它的请求已经完成,这就是异步。异步通知的方式一般是通过状态改变,消息通知,或者回调函数来完成,大多数时候采用的都是回调函数。(就像我们定制蛋糕,店家打电话跟我们说做好了,约个时间让我们过去拿)
二、阻塞和非阻塞
阻塞和非阻塞描述的是程序在等待调用结果(消息,返回值)时的状态。
1.阻塞:
阻塞调用是指调用方发出request(请求)的线程因为某种原因(如:等待系统资源)被服务方挂起,当服务方得到response(回复)后就唤醒挂起线程,并将response返回给调用方。
2.非阻塞:
非阻塞调用是指调用方发出request(请求)的线程在没有等到结果时不会被挂起,直到得到response(回复)后才返回。
阻塞和非阻塞最大的区别就是看调用方线程是否会被挂起。
大家可能还是有点不清楚,我再解释一下这两个名词。
阻塞和非阻塞在计算机的世界里面,通常指的是针对IO的操作,如网络IO和磁盘IO等。那么什么是阻塞和非阻塞呢?简单的说就是我们调用了一个函数之后,在等待这个函数返回结果之前,当前的线程是处于挂起状态,还是运行状态,如果是挂起状态,就意味着当前线程什么都不能干,就等着获取结果,这就叫同步阻塞,如果仍然是运行状态,就意味当前线程是可以的继续处理其他任务,但要时不时的去看下是否有结果了,这就是同步非阻塞。
三、举例深入理解
举个例子,比如我们去照相馆拍照,拍完照片之后,商家说需要30分钟左右才能洗出来照片,
这个时候如果我们一直在店里面啥都不干,一直等待商家面前等待它洗完照片,而且!我们啥都没干!就是干坐着!这个过程就叫同步阻塞(一定注意就是啥也没做的干等着)。
当然大部分人很少这么干,更多的是大家拿起手机开始刷视频打游戏,耍一会就问老板洗完没,老板说没洗完,然后我们接着看,再过一会接着问,直到照片洗完,这个过程就叫同步非阻塞(我们在等的同时,做了其他的事情,但是!我们还是在店里等带照片的洗完!)。
因为入职季节,越来越多的人过来,店里面空间越来越挤,老板说你把你手机号留下,我一会洗好了就打电话告诉你过来取,然后你去公园坐着,等待老板打电话,啥不都干(一定注意就是啥也没做的干等着,只不过换一个环境干等着),这个过程就叫异步阻塞。
当然很少有人这么干,我会去网吧打LOL,然后等待老板的电话。这样以来两不耽误,这个过程就叫异步非阻塞。(我不单单的只是等待照片喜好,而是可以去做其他的事情!)
四、图解
1.同步阻塞IO:
Sender:发送者,发送器
Receiver:接收者,接收器
针对Sender而言,请求发送出去以后,一直等到Receiver有结果了才返回,这是同步。在Sender获取结果的期间一直被block(阻塞)住了,也就是在此期间Sender不能处理其它事情,这是阻塞。
2.异步阻塞IO:
不存在!以后谁在说异步阻塞,直接上去一个大嘴巴子。我都异步,还玩阻塞???
3.同步非阻塞IO:
针对Sender而言,请求发送出去以后,立刻返回,然后再不停的发送请求,直到Receiver处理好结果后,最后一次发请求给Receiver才获得response。Sender一直在主动轮询,每一个请求都是同步的,整个过程也是同步的。在Sender等待Receiver的response期间一直是可以处理其它事情的(比如:可以发送请求询问结果),这是非阻塞。
4.异步非阻塞IO:
针对Sender而言,请求发送出去以后,立刻返回,然后再等待Receiver的callback,最后再次请求获取response,这整个过程是异步。在Sender等待Receiver的callback期间一直是可以处理其它事情的,这是非阻塞。
五、总结
本文主要介绍了同步,异步,阻塞和非阻塞的相关概念和例子。
从上面的描述中我们其实能够看到阻塞和非阻塞通常是指客户端在发出请求后,在服务端处理这个请求的过程中,客户端本身是否直接挂起等待结果,还是继续做其他的任务。
异步和同步,则是对于请求结果的获取是客户端主动等待获取,还是由服务端来通知消息结果。从这一点来看同步和阻塞其实描述的两个不同角度的事情,阻塞和非阻塞指的一个是客户端等待消息处理时的本身的状态,是挂起还是继续干别的。同步和异步指的对于消息结果的获取是客户端主动获取,还是由服务端间接推送。记住这两点关键的区别将有助于我们更好的区分和理解它们。