怎样理解阻塞非阻塞与同步异步的区别

作者:银月游侠

链接:https://www.zhihu.com/question/19732473/answer/88599695
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这几个概念,上面不少答案已经写得很清楚了。这里我结合自己的理解,简单地聊一下为什么这几个概念容易混淆。如果有错误之处,恳请批评指正。

我认为同步、异步、阻塞、非阻塞,是分3个层次的:

  1. CPU层次;
  2. 线程层次;
  3. 程序员感知层次。

这几个概念之所以容易混淆,是因为没有分清楚是在哪个层次进行讨论。

CPU层次
在CPU层次,或者说操作系统进行IO和任务调度的层次,现代操作系统通常使用异步非阻塞方式进行IO(有少部分IO可能会使用同步非阻塞轮询),即发出IO请求之后,并不等待IO操作完成,而是继续执行下面的指令(非阻塞),IO操作和CPU指令互不干扰(异步),最后通过中断的方式来通知IO操作完成结果。

线程层次

在线程层次,或者说操作系统调度单元的层次,操作系统为了减轻程序员的思考负担,将底层的异步非阻塞的IO方式进行封装,把相关系统调用(如read,write等)以同步的方式展现出来。然而,同步阻塞的IO会使线程挂起,同步非阻塞的IO会消耗CPU资源在轮询上。为了解决这一问题,就有3种思路:

  1. 多线程(同步阻塞);
  2. IO多路复用(select,poll,epoll)(同步非阻塞,严格地来讲,是把阻塞点改变了位置);
  3. 直接暴露出异步的IO接口,如kernel-aio和IOCP(异步非阻塞)。


程序员感知层次
在Linux中,上面提到的第2种思路用得比较广泛,也是比较理想的解决方案。然而,直接使用select之类的接口,依然比较复杂,所以各种库和框架百花齐放,都试图对IO多路复用进行封装。此时,库和框架提供的API又可以选择是以同步的方式还是异步的方式来展现。如python的asyncio库中,就通过协程,提供了同步阻塞式的API;如node.js中,就通过回调函数,提供了异步非阻塞式的API。

总结

因此,我们在讨论同步、异步、阻塞、非阻塞时,必须先明确是在哪个层次进行讨论。比如node.js,我们可以说她在程序员感知层次提供了异步非阻塞的API,也可以说在Linux下,她在线程层次以同步非阻塞的epoll来实现。



我觉得是理解的最透彻,解析的最好的回答。

以下是我的思考:

同步异步,阻塞非阻塞,常常难以区分。从不同层面来看,cpu层面,socket通信层面,程序员感知层面,这两个概念都会变化。当我们讨论这两个概念,要分层讨论。
现在常说的异步非阻塞,是指程序员感知层面。由于使用框架,框架封装后,给我们的感觉是异步非阻塞。如netty提供的接口是异步非阻塞。此时异步和非阻塞是同一个概念。
在框架实现层面,指socket层面。大多数采用的是同步非阻塞。netty nio底层实现就是同步非阻塞。最新netty底层实现支持异步非阻塞。此时异步和非阻塞就是两个不同的概念。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值