在Python的协程和多线程等相关的编程中,我们经常都会遇到这样几个专业名词——并发、并行、同步、异步、阻塞和非阻塞,很多童鞋都对这几个词有一定程度上的误解和混淆,在本篇我们就来讲讲这几个概念究竟有什么区别。

    一、并发和并行

    并发是指一个时间段内,有几个程序在同一个CPU上运行,但是任意时刻只有一个程序在CPU上运行。通俗讲就相当于是一个人交替做不同事情的能力,这里强调的是一个人来做。那为什么他要交替着做不同的事情呢?一般都是遇到有需要等待的事件,比如泡茶的时候,先把水烧上再去洗杯子、放茶叶。烧水是需要等待的(类似于IO这种耗时操作),在等待的时候我去做别的事(洗杯子、放茶叶),这就是并发。

    并行是指任意时刻点上,有多个程序同时运行在多个CPU上,所以最大并行数跟CPU的核数相同。这里强调的是多个人同时做不同的事情。比如在同一时间内,张三看书、李四听歌、王五玩游戏,几个人在做不同的事,这就是并行。

    二、同步和异步

    同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous communication)。

    同步是指代码调用IO操作时,必须等待IO操作完成才返回的调用方式。换句话说,就是由调用者主动等待这个调用的结果。要注意一点,这里说的IO操作并不仅仅是指狭义上的磁盘读写操作,而是泛指一切耗时操作,比如休眠、网络请求等,都属于IO操作这个范畴。

    异步跟同步正好相反,指代码调用IO操作时,不必等待IO操作完成就返回的一种调用方式。换句话说,当一个异步过程调用发出后,调用者不会立刻得到结果。而是在调用发出后,被调用者通过状态、通知来通知调用者,或通过回调函数处理这个调用。
    多线程就是一个典型的异步操作,比如通过线程池submit一个task之后,立即就会得到返回的一个future对象,后期我们就可以通过这个future对象去拿到异步操作的结果。

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

    三、阻塞和非阻塞

    阻塞和非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
    阻塞是指调用函数的时候当前线程被挂起。
    非阻塞是指调用函数的时候当前线程不会被挂起,而是立即返回。

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

    总结一下,阻塞非阻塞关心的是调用方(你自己)的行为,同步异步关心的是被调用方(书店老板)的行为,看起来比较相似,其实是从不同的角度去描述这件事。