在Python的协程和多线程等相关的编程中,我们经常都会遇到这样几个专业名词 —— 并发、并行、同步、异步、阻塞和非阻塞,很多童鞋都对这几个词有一定程度上的误解和混淆,在本篇我们就来讲讲这几个概念究竟有什么区别。
1. 并发和并行
并发是指一个时间段内,有几个程序在同一个CPU上运行,但是任意时刻只有一个程序在CPU上运行。通俗讲就相当于是一个人交替做不同事情的能力,这里强调的是一个人来做。
那为什么他要交替着做不同的事情呢?
一般都是遇到有需要等待的事件,比如泡茶的时候,先把水烧上再去洗杯子、放茶叶。烧水是需要等待的(类似于IO这种耗时操作),在等待的时候我去做别的事(洗杯子、放茶叶),这就是并发。
并行是指任意时刻点上,有多个程序同时运行在多个CPU上,所以最大并行数跟CPU的核数相同。这里强调的是多个人同时做不同的事情。比如在同一时间内,张三看书、李四听歌、王五玩游戏,几个人在做不同的事,这就是并行。
2. 同步和异步
同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)。
同步是指代码调用IO操作时,必须等待IO操作完成才返回的调用方式。换句话说,就是由*调用者*主动等待这个*调用*的结果。要注意一点,这里说的IO操作并不仅仅是指狭义上的磁盘读写操作,而是泛指一切耗时操作,比如休眠、网络请求等,都属于IO操作这个范畴。
异步跟同步正好相反,指代码调用IO操作时,不必等待IO操作完成就返回的一种调用方式。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在*调用*发出后,*被调用者*通过状态、通知来通知调用者,或通过回调函数处理这个调用。
多线程就是一个典型的异步操作,比如通过线程池submit一个task之后,立即就会得到返回的一个future对象,后期我们就可以通过这个future对象去拿到异步操作的结果。
举个通俗的例子:
你打电话问书店老板有没有《分布式系统》这本书,如果是同步通信机制,书店老板会说“你稍等,我查一下",然后开始查啊查,等查好了(可能是5秒,也可能是一天)告诉你结果(返回结果)。
而异步通信机制,书店老板直接告诉你我查一下啊,查好了打电话给你,然后直接挂电话了(不返回结果)。然后查好了,他会主动打电话给你。在这里老板通过“回电”这种方式来回调。注意,异步总是跟回调这个行为绑定在一起。
3. 阻塞和非阻塞
阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态。阻塞是指调用函数的时候当前线程被挂起。非阻塞是指调用函数的时候当前线程不会被挂起,而是立即返回。
还是上面的例子,你打电话问书店老板有没有《分布式系统》这本书,你如果是阻塞式调用,你会一直把自己“挂起”,直到得到这本书有没有的结果,如果是非阻塞式调用,你不管老板有没有告诉你,你自己先一边去玩了, 当然你也要偶尔过几分钟check一下老板有没有返回结果。在这里阻塞与非阻塞与是否同步异步无关。跟老板通过什么方式回答你结果无关。
总结一下,阻塞非阻塞关心的是调用方(你自己)的行为,同步异步关心的是被调用方(书店老板)的行为,看起来比较相似,其实是从不同的角度去描述这件事。
注:本文为蜗牛学院资深讲师卿淳俊老师原创,首发自公众号https://mp.weixin.qq.com/s/8qUyBrbAcDFZfbkGCzaVrQ,如需转载请私聊我处获得授权并注明出处。