其实想写这篇文章很久了, 因为最近总听到朋友在面试遇到相似的问题: 同步IO和阻塞IO的区别 什么是IO多路复用
, 诸如此类问题他们跟我说总回答的不尽人意, 最终含泪进入人才储备库 其实要理解这几个概念,有些人有些误区: 比如要么采取自嗨记忆法(不考虑脑容量,企图持久化记忆) 要么就是上来就跟面试官指点江山(这还好,起码还能说几句, 但是一旦面试官深入下去, 你的大刀可能就掏出来了)
所以笔者的建议是搞懂概念之前我们需要了解有关IO的一些先验知识: 尽管有些枯燥,但是如果你真的想指点江山不被问倒, 必不可少
对于操作系统内核相信非专业童鞋至少在一些方面有听说过, 笔者强烈建议去看看这方面的理论, 它概念比较繁杂 笔者从起初提的问题出发介绍内核: 它有三大支持功能:
通常对于进程和线程而言我们常常分为用户级进程(线程) 和系统级进程(线程) 俗称对应的用户空间 和内核空间, 必须明确 内核空间无法感知用户空间的存在 , 内核空间 仅仅和内核关联, 用户空间和内核无关 所以当发生系统调用
时 , 用户空间要切入内核空间,此时用户空间的进程将被阻塞, 只有内核空间完成系统调用返回给用户空间后, 方能唤醒改进程继续操作
系统调用: 用户空间发起一个需要内核才能完成的的操作: 比如你通过键盘输入 获取 IO设备的数据显示到你的界面上.
OK有了上面的基础后 我们再来谈最初的问题, 将迎刃而解 先图解 后说明
先来了解一张图,再细说二者关系
所谓同步IO
就是用户通过键盘方式(不一定是键盘) 用户空间感知用户操作转而向内核空间 发起IO操作让内核帮我们处理, 内核在拿到IO设备的数据后通过缓冲区开始同步数据到用户空间, 这个期间称为数据准备阶段, 而这个阶段内核会阻塞其他后续的IO请求, 只有在所有数据同步到用户空间后 才会唤醒用户空间的进程.继续处理其他操作
等说完阻塞IO再来看看二者之间的区别
所谓阻塞IO
就是输入获取 用户空间发起系统调用等待内核完成之前, 用户想要利用应用程序完成其他操作,但此时由于内核正在同步数据, 用户被迫等待. 所以这叫阻塞IO
从上面的解释中,你应该意识到同步IO和阻塞IO其实是一回事,都是阻塞的 仅仅是我们讨论的对象不同:
即同步IO的强调从
被调用对象
探讨阻塞 和 阻塞IO则是从调用着
角度探讨阻塞 本质是一个体系
联想一下你在登录QQ输入用户名和密码后发生了什么事情, 你对同步IO的记忆会更加深刻
注意一点:上面说的等待QQ处理结果不是指QQ服务器进行验证数据时的等待阶段, 而是当QQ需要从参数中的传递输入的QQ号和密码信息准备进行校验时,用户的等待阶段
还是先看图
异步IO 是相对与同步IO而言, 即当用户输入,用户空间发起IO操作请求时,不再需要操作系统进行同步刷新缓冲区到用户空间,而是仅仅把内核当作一个过道,IO数据直接经内核到用户空间, 所以一方面在响应速度更快,另一方面不需要让用户空间阻塞
而非阻塞IO是说用户在发起IO调用时, 用户无需等待即认为IO操作处理实时的 所以可以直接进行其他操作,
因此也可以发现异步IO和非阻塞IO其实也是一回事,仅仅是讨论对象不同
说完各自场景后,我们再来看看同步和异步的区别, 之前我们是对同一个问题研究不同对象的场景, 现在是对同一个问题和同一个讨论对象研究不同的实现方式 需要借助一个故事进行说明: 看过武侠小说或者电视剧的童鞋 想必都知道镖师这么一个机构
现在某钱庄老板A要运送一批货给自己的生意伙伴B, 这个时候A担心货物的安全问题, 于是请求龙门镖局(好像就它最有名)的镖师C代为押送,确保安全, 假定镖师是武林高手 我们来分析使用同步和异步进行处理的结果
如果是同步:
那么就是A和B谈好生意后, A开始发货, 于是B等待货物到来, 双方约定一手交钱一手交货, 即B只要没有收到货就就不会付钱,
那么这笔生意也就无法完成, 而对于A来说,在他把货物交给镖局那一刻,他就仅仅需要等等镖师把货物送到,然后收钱 (举杯庆祝…)
所以此时完成这笔交易的关键就在于镖师同步A的货物到B, 货物没送到那么B无条件等待 C其实也在等 B等待原因显而易见
而C等是因为镖局一旦接单 意味着一方面自己现在要着手准备人手押送货物, 另一方面就必须挂牌自己已经处于工作中, 无法接纳新的订单.
这个过程就是同步
还有一点: 镖师是感受不到B的存在, 他们只知道将货物送到规定的地点, 至于谁来取货,他们其实并不关心(别钻牛角尖哦)
如果是异步
:那简单了, 直接不考虑镖局, 但是并不代表镖局不存在, 只是说A足够自信能自己安全地将货物送给B(强盗呵呵一笑)
于是省去和镖局沟通和等待镖局发货,即省去那部分镖局的准备时间, 直接和B进行单方面沟通,
因此收货速度肯定要快许多,同时对于B而言,由于他知道A直接发货, 因此他可以确定这笔生意要成了, 等货物送到期间他没必要继续等待,
完全可以继续和D E F等谈新的生意, 从而扩展自己的业务 这个过程就是异步
异步决定在业务繁多(盗贼出现的频率就会加大)情况下, A 和 B 后面都无法确定这笔单是否能成
如果没有看过武侠小说,那么来个实际业务场景
比如我们在一个页面上提交表单:
如果是同步: 那么我们输入完表单信息后,通过
<input type = "submit" value="提交"/>
直接提交那么 在请求服务处理结果之前, 你的页面应该是在转圈圈(或者是其他显示进度的东西) 即如果你还想查看其他信息或者做其他页面操作 是不可能的即 这叫同步
如果是异步: 那么你应该通过Ajax提交
$.ajax(){}
那么提交过程首先不会出现整个页面转圈圈, 你完全利用这个时间去查看页面的其他信息, 不会收到影响. 这就是异步
这一篇消化后可以更进一步了解关于IO模型的相关知识
下一篇 IO多路复用 与 Reactor模式精讲 敬请期待!
利用这个时间去查看页面的其他信息, 不会收到影响. 这就是异步
这一篇消化后可以更进一步了解关于IO模型的相关知识
下一篇 IO多路复用 与 Reactor模式精讲 敬请期待!