同步阻塞/同步非阻塞、异步阻塞/异步非阻塞
同步阻塞/非阻塞,异步阻塞/非阻塞
声明:本篇思想非原创,系从老师处听来。因为CSDN发转载需要有原文链接,本篇没有原文链接,所以填的原创。
举个栗子
1、你在家做饭,用普通的汤锅,米放进去,就站在锅边,傻等饭熟。——这叫同步阻塞
单任务按顺序执行。
是不是觉得浪费了大量的时间,于是你想提高时间的利用效率。
2、还是用普通的汤锅,米放进去,然后继续回去打游戏,过一会就来看一次。——这叫同步非阻塞
多任务,定时查看任务执行状态。
时间的利用率稍微提升了一点点,还有没有办法再提升一点呢?
3、你去某宝淘了个电饭锅,饭熟了会自动跳闸的那种。米放进去,然后傻傻的看它怎么做饭的。——这叫异步阻塞
单任务,自动提交任务执行状态。
这有什么意义呢?完全没利用好电饭锅的优势啊
4、这回学聪明了,米放进去,按下按钮,然后就去打游戏了,等到跳闸的时候就去吃饭 。——这叫异步非阻塞
多任务,自动提交任务执行状态,合理分配,最大化利用资源。
这样是不是聪明了很多,时间的利用率大大提升。
相对于程序而言的 ,异步可以给你节省出更多的时间,让你去干别的事,同步只能由你自己主动去查看。
孰优孰劣不言而喻 。
阻塞和非阻塞,也很好理解。
同步阻塞,顺序执行,只能傻等,效率低下 。
同步非阻塞,稍微高明点,但是麻烦了很多,多做很多无用功。
异步阻塞,这个等于自断一臂,没啥大意义。
异步非阻塞,这才是异步的最佳用法。
一、同步与异步
同步与异步关注的是消息通信机制(synchronous communication/ asynchronous communication)。所谓同步,就是在发出一个调用时,在没有得到结果之前,该调用就不反回。但是一旦调用返回,就得到返回值了。换句话说,就是由调用者主动等待这个调用的结果。
而异步则是相反,调用在发出之后,这个调用就直接返回了,所以就没有返回结果。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出之后,被调用者通过“状态”、“通知”、“回调”三种途径通知调用者。
可以使用哪一种途径依赖于被带调用者的实现,除非被调用者提供多种选择,否则不受调用者控制。如果被调用者用状态来通知,那么调用者就需要每隔一定时间检查一次,效率就很低。如果使用通知和回调的方式,效率则很高。因为被调用者几乎不需要做额外的操作。
举个例子:
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说,你稍等,”我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。
二、回调函数
上面提到,回调是异步调用的一种实现方式。那么什么是回调函数呢?
- 概念
回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
- 举个例子
概念不是太好理解,我们举个例子。
沿用上面买书的例子,你的电话号码就叫回调函数,你把电话留给书店老板就叫登记回调函数,书店老板查好了叫做触发了回调关联的事件,老板给你打电话叫做调用回调函数。你接电话叫做响应回调事件。
- 代码实现(仅为了说明回调函数)
# coding=utf-8
import time
def call_back(): # 回调函数
print "我是回调函数"
def call_later(call_time, callback):
# 沉睡call_time后,调用回调函数
time.sleep(call_time)
callback()
if __name__ == '__main__':
call_later(10, call_back) # 登记回调函数
三、阻塞与非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。
阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。
接着上面的例子:
你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。
四、故事描述
老张爱喝茶,废话不说,煮开水。
出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。
- 老张把水壶放到火上,立等水开。(同步阻塞)老张觉得自己有点傻。
- 老张把水壶放到火上,去客厅看电视,时不时去厨房看看水开没有。(同步非阻塞)。
- 老张还是觉得自己有点傻,于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的噪音。
- 老张把响水壶放到火上,立等水开。(异步阻塞)。
- 老张觉得这样傻等意义不大,老张把响水壶放到火上,去客厅看电视,水壶响之前不再去看它了,响了再去拿壶。(异步非阻塞)。
- 所谓同步异步,只是对于水壶而言。普通水壶,同步;响水壶,异步。虽然都能干活,但响水壶可以在自己完工之后,提示老张水开了。这是普通水壶所不能及的。同步只能让调用者去轮询自己(情况2中),造成老张效率的低下。
- 所谓阻塞非阻塞,仅仅对于老张而言。立等的老张,阻塞;看电视的老张,非阻塞。
情况1和情况3中老张就是阻塞的,媳妇喊他都不知道。虽然3中响水壶是异步的,可对于立等的老张没有太大的意义。所以一般异步是配合非阻塞使用的,这样才能发挥异步的效用。