同步、异步、阻塞、非阻塞、回调等概念

结论

同步和异步是从任务完成后的通知机制来描述任务的概念,而阻塞和非阻塞是从任务提交者的角度来描述任务的。它们只是从不同的维度来描述任务。

另外,回调和同步、异步、阻塞、非阻塞不是一个层次的概念,虽然各种文章经常提到“异步回调”, 但是异步与回调并没有直接的联系,回调只是异步的一种可行的实现方式。当然同步回调也是存在的。

举例

以迅雷下载为例:迅雷下载东西完成时会发出“叮”的一声。

那么根据前面提到的两个维度来排列组合出来可能的任务:

人在观察任务有没有下载完,人作为下载任务的提交者,从人的角度,就有两种可能的方式:

  1. 人在提交下载任务后,啥都不干,等着任务下载完
  2. 人在提交下载任务后,去干其他事情,时不时跑来自己看有没有下载完

从任务通知的角度,迅雷在下载文件后会发出“叮”的一声,因此从是否发出“叮”的一声这个角度,也有两种可能的方式:

  1. 下载完成后,发出“叮”的一声
  2. 下载完成后,不发出“叮”的一声

把这两种方式进行排列组合,一共有2*2=4种情况:

  1. 任务下载时人不可以干其他事情,迅雷不发出声音;
  2. 任务下载时人不可以干其他事情,迅雷发出声音;
  3. 任务下载时人可以干其他事情,迅雷不发出声音;
  4. 任务下载时人可以干其他事情,迅雷发出声音。

同步和异步

迅雷发出声音,就是异步;迅雷不发出声音,就是同步

到底是同步还是异步,跟人是否等着任务完成没有关系,因为同步异步是从任务完成后的通知机制来描述任务的。只要有通知,就是异步;只要没有通知,就是同步。

阻塞和非阻塞

任务下载时人不可以干其他事情,就是阻塞;任务下载时人可以干其他事情,就是非阻塞

到底是阻塞还是非阻塞,跟迅雷是否发出声音没有关系,因为阻塞非阻塞是从任务提交者的角度来描述任务的。只要任务提交者在任务未完成时不能干其他事情,就是阻塞;只要能干其他事情,就是非阻塞。

回到例子

还是前面的例子:

  1. 任务下载时人不可以干其他事情,迅雷不发出声音;(同步,阻塞)

    同步体现在:下载完成后迅雷不会发出“叮”的一声通知你任务完成
    阻塞体现在:任务下载未完成时,人不可以干其他事情

  2. 任务下载时人不可以干其他事情,迅雷发出声音;(异步,阻塞)

    异步体现在:下载完成后迅雷发出“叮”的一声通知你任务下载完成
    阻塞体现在:任务下载未完成时,人不可以干其他事情

  3. 任务下载时人可以干其他事情,迅雷不发出声音;(同步,非阻塞)

    同步体现在:迅雷不会发出声音通知你任务完成
    非阻塞体现在:任务下载未完成时,人可以干其他事情

  4. 任务下载时人可以干其他事情,迅雷发出声音。(异步,非阻塞)

    异步体现在:下载完成后迅雷发出“叮”的一声通知你任务下载完成
    非阻塞体现在:任务下载未完成时,人可以干其他事情

和 IO 联系

Java中有三种IO:BIO/NIO/AIO,按照上面的说法:

  • BIO:同步阻塞

    磁盘完成IO后会通知内核,这个其实从内核的角度看属于异步;但是从上层API调用的角度还是属于同步,因此这里将它算作同步。

  • NIO:同步非阻塞
  • AIO:异步非阻塞

按照排列组合应该有4种情况啊,上面只有3种,仔细一看发现缺少了异步阻塞,Java类库为什么没有呢?

以前面迅雷下载的例子为例,异步阻塞相当于:人提交了下载任务给迅雷,任务完成后迅雷会发出声音通知人,但是人提交任务后啥都不干,坐在那里等着迅雷发出声音... (这种行为感觉有点智障吧)。

进一步联系到Linux的传统IO和IO多路复用:

  1. read,write,fopen等这类函数,是同步阻塞,Java-BIO 的 OS 模型;
  2. select/poll模型,是同步非阻塞,Java-NIO 的 OS 模型;
  3. epoll模型,是异步非阻塞。

你可能感兴趣的:(同步、异步、阻塞、非阻塞、回调等概念)