同步与阻塞

以socket.read()为例子:

  • 同步阻塞模型:传统的BIO里面socket.read(),如果TCP RecvBuffer里没有数据,函数会一直阻塞,直到收到数据,返回读到的数据。

  • 同步非阻塞模型:对于NIO,如果TCP RecvBuffer有数据,就把数据从网卡读到内存,并且返回给用户;反之则直接返回0,永远不会阻塞。

  • 异步非阻塞模型:最新的AIO(Async I/O)里面会更进一步:不但等待就绪是非阻塞的,就连数据从网卡到内存的过程也是异步的。

换句话说,BIO里用户最关心“我要读”,NIO里用户最关心"我可以读了",在AIO模型里用户更需要关注的是“读完了”。

NIO一个重要的特点是:socket主要的读、写、注册和接收函数,在等待就绪阶段都是非阻塞的,真正的I/O操作是同步阻塞的(消耗CPU但性能非常高)。

阻塞与非阻塞指的的是当不能进行读写(网卡满时的写/网卡空的时候的读)的时候,I/O 操作立即返回还是阻塞;同步异步指的是,当数据已经ready的时候,读写操作是同步读还是异步读

同步和异步是针对的时被调用者的描述

理解这两个概念,可以用去银行办理业务(可以取钱,也可以存钱)来比喻:
当到银行后,
.可以去ATM机前排队等候 -- (排队等候)就是同步等待消息
.可以去大厅拿号,等到排到我的号时,
柜台的人会通知我轮到我去办理业务. -- (等待别人通知)就是异步等待消息.

  • 同步指的是,被调用者在结束后不会通知调用者,
  • 异步指的是,被调用者在结束后会通知调用者

阻塞和非阻塞针对的是调用者

  • 阻塞指的是调用者在等待一个函数执行时不做别的事,就一直干等
  • 非阻塞指的是调用者在等待一个函数执行的同时去做别的事,使用轮询或者回调的方式在这个函数执行完成后再进行下一步操作

列子

  • 先来看同步场景中是如何包含阻塞和非阻塞情况的
    我们是用传统的水壶烧水。在水烧开之前我们一直做在水壶前面,等着水开。这就是阻塞的。
    我们是用传统的水壶烧水。在水烧开之前我们先去客厅看电视了,但是水壶不会主动通知我们,需要我们时不时的去厨房看一下水有没有烧开。这就是非阻塞的。

  • 再来看异步场景中是如何包含阻塞和非阻塞情况的
    我们是用带有提醒功能的水壶烧水。在水烧发出提醒之前我们一直做在水壶前面,等着水开。这就是阻塞的。
    我们是用带有提醒功能的水壶烧水。在水烧发出提醒之前我们先去客厅看电视了,等水壶发出声音提醒我们。这就是非阻塞的。

原文地址:https://www.cnblogs.com/zhz-8919/p/10789546.html