各种IO模型,一篇打尽

 

一、阻塞/非阻塞-同步非同步

 

同步/异步

同步请求:A调用B,B的处理是同步的,在处理完之前他不会通知A,只有处理完之后才会明确的通知A;

异步请求:A调用B,B的处理是异步的,B在接到请求后先告诉A我已经接到请求了,然后异步去处理,处理完之后通过回调等方式再通知A。

 

同步/异步区别

同步和异步最大的区别就是被调用方的执行方式和返回时机;

同步指的是被调用方做完事情之后再返回;

异步指的是被调用方先返回,然后再做事情,做完之后再想办法通知调用方。

 

阻塞/非阻塞

阻塞请求:A调用B,A一直等着B的返回,别的事情什么也不干;

非阻塞请求:A调用B,A不用一直等着B的返回,先去忙别的事情了。

 

阻塞/非阻塞区别

阻塞和非阻最大的区别就是在被调用方返回结果之前的这段时间内,调用方是否一直等待。

阻塞指的是调用方一直等待,别的事情什么都不做;

非阻塞指的是调用方先去忙别的事情。

 

阻塞/非阻塞和同步/异步的区别

阻塞、非阻塞和同步、异步其实针对的对象是不一样的

阻塞、非阻塞说的是调用者

同步、异步说的是被调用者

 

二、Linux(UNIX)操作系统五种IO模型

什么是IO

拿一次磁盘文件读取为例,我们要读取的文件是存储在磁盘上的,我们的目的是把它读取到内存中。可以把这个步骤简化成把数据从硬件(硬盘)中读取到用户空间中。

一次完整的钓鱼(IO)操作,是鱼(文件)从鱼塘(硬盘)中转移(拷贝)到鱼篓(用户空间)的过程。

阻塞IO模型

阻塞 I/O 是最简单的 I/O 模型,一般表现为进程或线程等待某个条件,如果条件不满足,则一直等下去。条件满足,则进行下一步操作。

应用程序进行 recvfrom 系统调用时将阻塞在此调用,直到该套接字上有数据并且复制到用户空间缓冲区。该模式一般配合多线程使用,应用进程每接收一个连接,为此连接创建一个线程来处理该连接上的读写以及业务处理。

 

非阻塞IO模型

应用进程与内核交互,目的未达到之前,不再一味的等着,而是直接返回。然后通过轮询的方式,不停的去问内核数据准备有没有准备好。如果某一次轮询发现数据已经准备好了,那就把数据拷贝到用户空间中。应用进程通过 recvfrom 调用不停的去和内核交互,直到内核准备好数据。如果没有准备好,内核会返回error,应用进程在得到error后,过一段时间再发送recvfrom请求。在两次发送请求的时间段,进程可以先做别的事情。

 

IO复用模型

多个进程的IO可以注册到同一个管道上,这个管道会统一和内核进行交互。当管道中的某一个请求需要的数据准备好之后,进程再把对应的数据拷贝到用户空间中。

IO多路转接是多了一个select函数,多个进程的IO可以注册到同一个select上,当用户进程调用该select,select会监听所有注册好的IO,如果所有被监听的IO需要的数据都没有准备好时,select调用进程会阻塞。

 

信号驱动IO模型

应用进程在读取文件时通知内核,如果某个 socket 的某个事件发生时,请向我发一个信号。在收到信号后,信号对应的处理函数会进行后续处理。

 

异步IO模型

应用进程把IO请求传给内核后,完全由内核去操作文件拷贝。内核完成相关操作后,会发信号告诉应用进程本次IO已经完成。

 

5种IO模型对比

 

三、Java中的三种IO模型

 

java IO模型和操作系统IO模型关系

Java中的IO还是借助操作系统的IO模型的,只不过是对操作系统IO模型的封装而已啦。

可以把Java中的BIO、NIO和AIO理解为是Java语言对操作系统的各种IO模型的封装。

java中提供的IO有关的API,在文件处理的时候,其实依赖操作系统层面的IO操作实现的。

比如在Linux 2.6以后,Java中NIO和AIO都是通过epoll来实现的,而在Windows上,AIO是通过IOCP来实现的。

 

阻塞IO(BIO)

同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。

BIO (Blocking I/O):有一排水壶在烧开水,BIO的工作模式就是,叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

BIO和NIO都是同步的IO模型,即同步阻塞IO和同步非阻塞IO

 

非阻塞IO(NIO)

同时支持阻塞与非阻塞模式,但主要是使用同步非阻塞IO。

NIO (New I/O):NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

 

异步IO(AIO)

异步非阻塞I/O模型。

异步IO指的是异步非阻塞IO。

AIO ( Asynchronous I/O):为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。

 

四、Reactor 模式

 

Reactor 模式跟 IO 模型关系

Reactor 模式跟 IO 模型中的 IO 多路复用模型非常相似

IO 多路复用模型可以看成是 Reactor 模式在 IO 模型上的应用

Reactor 模式在进程-线程模型上的应用。

 

1. 单进程单线程

只有一个进程,监听套接字和连接套接字上的事件都由 Select 来处理。

过程

(1) 如果有建立连接的请求过来,Acceptor 负责接受并与之建立连接,同时将连接套接字加入 Select 进行监听。

(2) 如果某个连接上有读事件则进行 Read->业务处理->Write 等操作。

(3) 如此循环反复。

缺点:会有阻塞,在进行业务处理的时候不能进行其他操作:如建立连接,读取其他套接字上的数据等。

 

2. 单进程多线程

与单进程单线程类似,不同的是该模型将业务处理放在线程中,进程就不会阻塞在业务处理上。

优点:比较完美的进程-线程模型,在 Java 实现中复杂度也不高,很多网络库都是基于此,比如 Netty 。

 

3. 多进程单线程

与非 Reactor 模式中的多进程单线程相似,只是本模式在子进程中使用了 IO 多路复用,实用性一下就上来了。大名鼎鼎的 nginx 就采用这种进程-线程模型。

缺点:子进程还是会阻塞在业务处理上。

 

4. 多进程多线程

 

5. 主从进程多线程

前面几种 Reactor 模式的进程-线程模型中,连接的建立和连接的读写都是在同一进程中。本模型中将连接的建立和连接读写放在不同的进程中。

过程

(1) 主进程在监听套接字上 Select 阻塞,一旦有请求过来则与之建立连接,并将连接套接字传递给从进程。

(2) 从进程在连接套接字上 Select 阻塞,一旦连接上有数据过来则进行 Read,并将业务通过线程来处理。如果有必要还会向连接 Write 数据。

 

五、常见组件使用的模型

netty-主从-多线程

 

tomcat-单进程多线程

 

redis-单进程单线程

 

ngnix-多进程单线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值