同步与异步,阻塞与非阻塞
“同步与异步,阻塞与非阻塞”这个概念,在讨论io和并发两个场景中有什么不同?该怎么理解?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
“同步与异步,阻塞与非阻塞”这个概念,在讨论io和并发两个场景中有什么不同?该怎么理解?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(4)
今天早上关注了这个问题,刚抽出时间大概整理下,以下仅是个人理解:
一定要多看几遍代码并结合文字理解下
引
引自
践
1、阻塞式I/O式
客户端代码
服务端代码
2、非阻塞式I/O
客户端代码同上
服务端代码
3、多路复用式I/O(基于非阻塞式I/O)
客户端代码同上
服务端代码
4、信号驱动式I/O
JAVA没有实现
5、异步I/O
客户端代码同上
服务端代码
结
牛奶工送牛奶场景
阻塞式:每天早上自己去小区门口等牛奶工
非阻塞式:每天早上在家从窗户早上隔3分钟看看牛奶工到了没,到了的话去拿
多路复用式:每天早上由小区门卫室接待所有牛奶工,到了会给住户发短信,你马上去拿
信号驱动式:每天早上牛奶工到了会给你发短信,你马上去拿
异步式:每天早上牛奶工直接放到小区住户牛奶柜并发短信,不需要现在去拿
它
程序分为
CPU
计算型和I/O
读写型,线程尤其是被内核调度的线程是及其珍贵的资源(JAVA
计划在JDK
将来的版本实现由JVM
”自己“调度的轻型线程),在有限的线程资源下CPU
计算型程序不但不会有明显提升,反而由于频繁的上下文切换导致性能下降(这也是Redis
这种基于内存的数据库采用单工作线程并且速度非常快的原因,另一个重要的原因是单线程导致了不用为共享资源给线程加/解锁造成人为阻塞),而在I/O
读写型的程序中,多线程工作在以上五种模式下性能是逐步提升的(最后多说一句,还是以Redis
举例,不管是Jedis-Pool
这种池化客户端还是Lettuce
这种单连接客户端,当多用户接入Redis
服务器时一定是多连接的,这时候就要用到多路复用来处理用户请求了,至于为什么没有用异步,一个原因是工作线程是单线程,另一个原因是异步I/O
模型在性能提升方面有限并且复杂度高,以至于Netty
在新版本的包中把这种模式删除了)同步IO,由用户程序主动去调用系统调用获知读写是否已经就绪。
异步IO,内核当读写就绪时,会回调通知用户程序。
阻塞IO,用户程序调用系统调用,如果没有就绪,内核不会返回,用户程序阻塞等待。
非阻塞,用户程序调用系统调用,如果没有就绪,内核立刻返回,用户程序不会阻塞等待。
一般来讲,按语义来说就分为同步阻塞,同步非阻塞,异步(非阻塞)三种。
阻塞IO:请求进程一直等待IO准备就绪。
非阻塞IO:请求进程不会等待IO准备就绪。
同步IO操作:导致请求进程阻塞,直到IO操作完成。
异步IO操作:不导致请求进程阻塞。
举个小例子来理解阻塞,非阻塞,同步和异步的关系,我们知道编写一个程序可以有多个函数,每一个函数的执行都是相互独立的,但是 对于一个程序的执行过程,每一个函数都是必须的,那么如果我们需要等待一个函数的执行结束然后返回一个结果(比如接口调用),那么我们说该函数的调用是阻塞的,对于至少有一个函数调用阻塞的程序,在执行的过程中,必定存在阻塞的一个过程,那么我们就说该程序的执行是同步的,对于异步自然就是所有的函数执行过程都是非阻塞的。
这里的程序就是一次完整的IO,一个函数为IO在执行过程中的一个独立的小片段。
同步与异步
阻塞与非阻塞