今天我阅读了一篇小漫画文章,其中用了一串故事串通了5个io模型,我觉得很好的助力我进行了理解。特此我进行一个简单的总结。原文贴在末尾哦。
linux的IO模型主要分为5种,阻塞IO、非阻塞IO、多路复用IO、信号量通知IO、异步IO。如果理解了这几个模型,那么将很有效的帮助我们更深刻和简单的理解到底在java中什么是io模型,她们的区别又是什么呢。
首先讲下故事前提,有助于我们理解系统中名词及io过程。
我们都知道钓鱼,鱼在荷塘内,当我们坐在荷塘边,手里一直握着鱼竿等待鱼上钩,当鱼竿抖动,我们立马拉起鱼竿将鱼放入鱼篓内,这个钓鱼的过程也就完成了。
一次完整的钓鱼(IO)操作,是鱼(文件)从鱼塘(硬盘)中转移(拷贝)到鱼篓(用户空间)的过程
一、阻塞IO
❣ 今天我去荷塘边钓鱼,钓鱼的过程中,我一直紧紧握着鱼竿,静静等待鱼上钩,在这个过程中我哪儿都不去,不做其他事情,就等鱼上钩。
这就是阻塞IO,我们在等待读取文件的过程中,不做其他操作,只等文件读取成功,从内核态拷贝到用户态。我们也很容易理解,阻塞IO是很简单的,但是也是耗时的。
二、非阻塞IO
❣ 我觉得我钓鱼过程中,我还想去逛逛淘宝,买点衣服,不然太无聊了,所以我就将鱼竿架在旁边。我逛一会淘宝,就过来瞅一眼有没有鱼上钩,鱼没上钩我继续逛,一会接着我再来查看,当某一次看到鱼上钩了以后,立马收鱼线,将鱼放入鱼篓内。
这就是非阻塞IO,我们在等待读取文件的过程中,如果数据还没准备好,那我可以先做其他的,通过一个轮询,我们过一会就查询下数据是否准备完毕,当某次轮询查询到数据已经准备好时,我们就将数据从内核拷贝到用户态。
三、信号量通知IO
❣ 在钓鱼的时候,我虽然逛着淘宝,但是每逛一会我就得看看鱼有没有上钩,太麻烦了,所以我买了一个感应报警器,当鱼上钩抖动的时候,报警器自动报警,我再过去将鱼拉上来放入鱼篓,岂不是美滋滋。
这就是信号量通知IO,我们系统会告诉内核,当数据准备好可以拷贝时,通过一个信号量通知到程序,在此过程中,我可以随便去做其他事情,也无需轮询关心数据是否准备完毕,而当程序收到信号量以后,知道数据已经可以进行拷贝,在切回程序将数据从内核拷贝到用户态。
四、多路复用IO
❣ 我觉得在钓鱼的时候,一根杆子只能钓一条鱼,收获太少了,我想一次性多钓一点鱼鸭,这样我就能早点回家,老婆就不会嫌我钓鱼这么慢还钓得少了啊。所以我想了一个办法,我把多个鱼竿绑在一根大的竹竿上,我就握着这根竹竿,当竹竿上的某一根鱼竿抖动的时候,我就立马拿起这一根鱼竿把鱼钓起来,放入鱼篓中。
这就是多路复用IO,我们可以通过一个select指令将多个io注册到同一个通道内,当通道内的某一个io数据准备好可以读取时,我们可以将数据读取出来。只是在这个过程中,我们也是要紧紧看着这个通道的。
五、异步IO
❣ 我在钓鱼的时候,虽然可以去做其他事情,也可以安装一个报警器来通知我,但是把,当鱼上钩的时候,我还是得自己一个人跑过去将鱼拉上来,放入鱼篓,我觉得很辛苦。所以我干脆花了大手笔,买了一个自动钓鱼竿!这样,当鱼上钩的时候,这个鱼竿就能帮我自动把鱼钓上来,放入鱼篓了,岂不是更省事??
这就是异步IO,这个才是真正的实现了异步。在之前的前几种IO模型中,全部都是基于同步模式。虽然消息的通知,钓鱼的过程我们是异步的,但是实际上,我们只是知道鱼上钩了而已,我们将鱼抓起来放入鱼篓,也就是将数据从内核拷贝到用户态的过程,都是需要自己去完成的,也就是同步的。而异步IO是在数据准备完毕的同时,还将数据替我们拷贝到了用户态,我们真正的解放了双手,这才属于异步!
有人说,那带有报警器的烧水壶也不属于同步咯?这样表达是错误的。因为我们在烧水器报警的同时,水已经烧好了,这属于异步。而钓鱼的时候,报警器响了,但是鱼并没上来,鱼放入鱼篓的过程还未完成,钓鱼这个事情还未完全实现,怎么能属于异步呢?你品,你细品。所以我们最终有了一个异步IO。我们也很好的去区分异步与同步的区别了。
喜欢点个赞哦,特此感谢原作者的体贴解释。