【vert.x准备篇1】同步和异步,阻塞和非阻塞概念澄清

为了能更好的理解vert.x的线程模型,我们必须要先明确几个概念:同步(Synchronous)和异步(Asynchronous),阻塞(Blocking)和非阻塞(Non-Blocking)。关于这几个名词的解释网络上也是众多纷纭,每个人说法都不太一样,但说的又似乎很有道理。其实造成这种情况的最主要原因是这四个概念并不是完全隔离、互斥的,而是相互之间有重叠。例如,当提到异步时那调用一定是非阻塞的,提到同步时则一定会有阻塞调用,此谓之重叠;然而如果我们在谈异步,那在调用方的角度来看是一定不存在阻塞的情况发生的,此谓之互斥。下面我们详细聊聊对于这几个名词大家应该如何理解。

我们以在单线程环境下调用功能为读取文件内容的方法readFile(filename)为例来模拟一下都会发生什么:

  • 阻塞

调用此方法后主线程进入阻塞状态,期间不能执行任务操作,一直到readFile()返回才能继续执行后面的代码。

  • 非阻塞

调用此方法后,readFile()立刻返回,主线程可以继续执行后面的代码而不需要等待磁盘I/O操作完成。但这里会产生一个问题,主线程怎么才能知道readFile()是否完成?是会有人通知这一事件,还是主线程主动去轮询呢?

  • 同步

其实同步/异步是一个比阻塞/非阻塞更加广泛的概念。我们在说阻塞时,一定是在描述某种I/O操作,比如文件读写和网络收发。而对于同/异步来说则可以用来描述更多的行为,比如对于HTTP协议来说,请求方发起请求后必须要一直等待,直到收到响应才能再次发起其他请求,这就是一种同步,即需要等待你要做的事完成才能继续后面的事。对于readFile()的调用来说,同步则是指主线程必须等待readFile()返回(即干完了事)才能继续执行后面的代码,这点跟阻塞是完全相同的。也就是说,当我们描述一个方法是同步调用时,则也是在描述这同时也是一个阻塞调用。

可能有朋友会提及一种"同步非阻塞"的概念,即调用readFile()时会马上返回,此为非阻塞,但是后续还需要主线程停止执行其他代码来主动去查询此方法是否完成,此为同步。其实这种说法也是对的,因为上面说过了,同步是一种宽泛的概念,对于这种场景来说,无论"查询"动作是阻塞的还是死循环在查,对于主线程来说它其实是没有机会干其他事的,即无法执行后面的代码,这其实就是广义上的同步。

  • 异步

我们在描述某个方法是异步的时候,其实同时也是在描述这个方法是非阻塞的,这是二者概念上的相同之处。前面在讨论非阻塞时抛出了一个关于调用方到底如何获悉readFile()是否完成的问题,这里就可以回答了。在编程领域,异步除了是在表明方法调用为非阻塞外,也是在暗示调用方并不需要主动查询任务完成情况,而是会"被动"通知。而发起这个通知的"人",往往是操作系统,即操作系统会通过某种方式通知进程,告诉它你所关心的I/O操作已经完成了。为什么用往往呢,还是那句话,异步是一个广泛的概念,除了操作系统 ,我们也可以在用户进程中自己实现这种通知。也就是说谁通知的并不重要,重要的是调用方并不需要主动查询

总结,同步和异步,阻塞和非阻塞这4个概念是相互交叉的,它们既有区别,也有重叠之处。其中,同步更强调调用方需要主动查询子任务是否完成,而异步则强调调用方会被动的收到子任务完成的通知,此期间调用方都可以继续执行其他代码。

下一篇会讲解reactor(反应堆)线程模型的相关知识。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章