java --- BIO NIO AIO

概述

      本文将会介绍 unix 系统中 IO 的 5 种模式,在后续的文章后会介绍 reactor 和 Proactor 两种IO模式。php

异步和阻塞

       咱们先来大概了解了一下异步和阻塞的问题。 能够查看一下两个连接 : html

https://www.zhihu.com/question/19732473/answer/20851256java

https://www.zhihu.com/question/19732473/answer/14413599react

 

阻塞非阻塞: 请求不能当即获得应答,须要等待,那就是阻塞;不然能够理解为非阻塞。 多线程

同步异步: 某业务须要甲乙甚至多方合做的时候, 并发

  1. 老是按照“甲方请求一次,乙方应答一次”这样的有序序列处理业务,只有当“一次请求一次应答”的过程结束才能够发生下一次的“一次请求一次应答”,那么就说他们采用的是同步。(同步IO中对同一个描述符的操做必须是有序的
  2. 若是甲方只要有须要,就会发送请求,无论上次请求有没有获得乙方应答。而乙方只要甲方有请求就会接受,不是等此次请求处理完毕再接受甲方新请求。这样请求应答分开的序列,就能够认为是异步。异步状况下,请求和应答不须要一致进行,可能甲方后请求的业务,却先获得乙方的应答。同步是线性的,而异步能够认为是并发的。(异步IO中,异步IO能够容许多方同时对同一个描述符发送IO请求,或者一次发多个请求,固然有机制保证如何区分这些请求,

做者:Shihui wang
连接:https://www.zhihu.com/question/19732473/answer/14413599异步

       能够这样理解 : 同步异步关注的是协做方式,而阻塞和非阻塞则是遇到IO操做时,请求者当时的状态。async

 

5种 IO 模式       

        UNIX 5种IO 模式,分别是 函数

  • blocking IO   阻塞IO
  • non-blocking IO  非阻塞IO 
  • io multiplexing  多路复用IO
  • asynchronous IO  异步IO
     

       因为signal driven IO在实际中并不经常使用,因此我这只说起剩下的四种IO Model。了解4种模式以前咱们须要注意这些知识点。学习

 

  IO发生时涉及的对象和步骤。

       对于一个network IO (这里咱们以read举例),它会涉及到两个系统对象,一个是调用这个IO的process (or thread),另外一个就是系统内核(kernel)。当一个read操做发生时,它会经历两个阶段:
1.  等待数据准备 (Waiting for the data to be ready)
2.  将数据从内核拷贝到进程中 (Copying the data from the kernel to the process)

 

线程数量

       同时咱们还须要知道一点,对于请求,是否是建立越多的线程就越好呢?建立的线程应该和底层机器能够承受的线程数量有关,具体的能够看这篇文章,多个请求对应太多的线程有可能会致使太多的内存开销和时间分片,多个线程会致使CPU 切换线程带来的开销,咱们学习计算机操做系统知道当切换线程时须要从新将以前线程执行的信息从新加载到主存中,可是有可能因为缓冲机制(例如LRU)将会淘汰掉某些信息,信息的加载将会带来时间开销。

     

blocking IO

       阻塞 IO ,能够用下面的图来表示 :

 

blockingIO

       能够看到 process 进程一直阻塞在调用 recvfrom 以后,一直到内核返回 ok .

 

non-blocking IO 

       从图中能够看出,当用户进程发出read操做时,若是kernel中的数据尚未准备好,那么它并不会block用户进程,而是马上返回一个error。从用户进程角度讲 ,它发起一个read操做后,并不须要等待,而是立刻就获得了一个结果。用户进程判断结果是一个error时,它就知道数据尚未准备好,因而它能够再次发送read操做。一旦kernel中的数据准备好了,而且又再次收到了用户进程的system call,那么它立刻就将数据拷贝到了用户内存,而后返回。
       因此,用户进程实际上是须要不断的主动询问kernel数据好了没有
non-blocking

 

IO multiplexing

       多路复用 IO , 它将会首先调用select 函数,当数据没准备好,进程依旧会被阻塞,当内核数据准备好,它会通知一下用户进程,用户进程调用 recvfrom 函数,进入第二次阻塞,等内核将数据成功拷贝到用户进程的时候,用户进程成功返回。过程以下 :

 

mult

       能够知道,多路复用会比以前的模式多了一次函数调用,上面咱们也可使用 多线程+ 阻塞IO 的方式来实现,那么多路复用这种方式又在哪里呢?使用select能够处理更多的connection, select/epoll的优点并非对于单个链接能处理得更快,而是在于能处理更多的链接。实际中咱们会使用 non-blocking  + 多路复用,这样轮询是否有事件到来的请求就交给 select 来完成就能够了。

 

Asynchronous I/O

        用户进程发起read操做以后,马上就能够开始去作其它的事。而另外一方面,从kernel的角度,当它受到一个asynchronous read以后,首先它会马上返回,因此不会对用户进程产生任何block。而后,kernel会等待数据准备完成,而后将数据拷贝到用户内存,当这一切都完成以后,kernel会给用户进程发送一个signal,告诉它read操做完成了。

asynose

 

总结

       这篇文章,咱们知道了阻塞与非阻塞,异步同步之间的区别,了解了5中 IO 模式,在后续的文章咱们会深刻Reator 模式和java NIO实现。

 

参考资料

相关文章
相关标签/搜索