关于阻塞非阻塞,同步异步的最好解释

还是不同层次的问题……
一个网络包从应用程序A发到另一台电脑上的应用程序B,需要经历:

  1. 从A的业务代码到A的软件框架
  2. 从A的软件框架到计算机的操作系统内核
  3. 从A所在计算机的内核到网卡
  4. 从网卡经过网线发到交换机等设备,层层转发,到达B所在计算机的网卡
  5. 从B所在计算机的网卡到B所在计算机的内核
  6. 从B所在计算机的内核到B的程序的用户空间
  7. 从B的软件框架到B的业务代码

这个层级关系就像是过程调用一样,前一级调用后一级的功能,后一级返回一个结果给前一级(比如:成功,或者失败)。只有在单独一级的调用上,可以说同步还是异步的问题。所谓同步,是指调用协议中结果在调用完成时返回,这样调用的过程中参与双方都处于一个状态同步的过程。而异步,是指调用方发出请求就立即返回,请求甚至可能还没到达接收方,比如说放到了某个缓冲区中,等待对方取走或者第三方转交;而结果,则通过接收方主动推送,或调用方轮询来得到。

从这个定义中,我们看:

  • 首先1和7:这取决于软件框架的设计,如果软件框架可以beginXXX,然后立即返回,这就是一种异步调用,再比如javascript当中的异步HTTP调用,传入参数时提供一个回调函数,回调函数在完成时调用,再比如协程模型,调用接口后马上切换到其他协程继续执行,在完成时由框架切换回到协程中,这都是典型的异步接口设计。

  • 2和6:其他答主已经说得很好了,其实都需要调用方自己把数据在内核和用户空间里搬来搬去,其实都是同步接口,除非是IOCP这样的专门的异步传输接口,所以这一级其实是同步的,阻塞与非阻塞的区别其实是影响调用接口的结果(在特定条件下是否提前返回结果),而不是调用方式。

  • 3和5:内核一般通过缓冲区,使用DMI来传输数据,所以这一步又是异步的。

  • 4:以太网是个同步时序逻辑,随信号传输时钟,必须两边设备同时就绪了才能开始传输数据,这又是同步的。

总结来说,讨论究竟是异步还是同步,一定要严格说明说的是哪一部分。其他答主说非阻塞是同步而不是异步,这毫无疑问是正确的,然而说某个框架是异步IO的框架,这也是正确的,因为说的其实是框架提供给业务代码的接口是异步的,不管是回调还是协程,比如说我们可以说某个库是异步的HTTPClient,并没有什么问题,因为说的是给业务代码的接口。由于通常异步的框架都需要在2中使用非阻塞的接口,的确会有很多人把非阻塞和异步混为一谈。

编程的时候我们写业务代码,基本就是把IO多路复用(事件注册)认为是异步非阻塞的,虽然在linux接口层次还是同步阻塞的。

参考文章:https://www.zhihu.com/question/19732473/answer/117012135


关于阻塞非阻塞,同步异步的最好解释
http://yoursite.com/2019/10/17/编程开发/Java/关于阻塞非阻塞,同步异步的最好解释/
作者
Wei Lyu
发布于
2019年10月17日
许可协议