IO的四种模型
同步和阻塞的概念
阻塞:阻塞IO指的是需要内核IO操作彻底完成后,才返回到用户空间执行用户的操作。
同步:同步IO是指用户空间的现成主动发起IO请求,内核空间被动接受。异步IO就是反过来。
模型
- 同步阻塞IO(BIO)
- 同步非阻塞IO(NIO)
- IO多路复用
- 异步IO
同步阻塞IO
java中默认情况下,socket连接的IO操作都是BIO。
java应用程序从IO系统调用开始,知道系统调用返回,java进程是阻塞的。
如图:
优点:应用程序开发简单;在阻塞等待数据期间,用户现成挂起。
缺点:需要大量的线程来维护大量的网络连接,内存、现成切换开销回非常巨大。
同步非阻塞NIO
socket连接默认是阻塞模式,在linux系统下,可以通过设置将socket变成非阻塞的模式。
应用程序开始IO系统调用后,会出现以下两种情况:
(1)在内核缓冲区中没有数据的情况下,系统调用会立即返回,返回一个调用失败的信息。
(2)在内核缓冲区中有数据的情况下,是阻塞的,直到数据从内核缓冲复制到用户进程缓冲。复制完成后,系统调用返回成功,应用进程开始处理用户空间的缓存数据。
优点:每次发起IO系统调用,在内核等待数据过程中可以立即返回。用户现成不会阻塞,实时性较好。
缺点:不断轮训内核,这将占用大量的CPU时间,效率低下。
同步非阻塞IO,可以简称为NIO,但是它不是java中的NIO。java的NIO(New IO)对应的多路复用模型。
IO多路复用
IO多路复用模型可以解决同步非阻塞IO模型中轮询等待的问题。
IO多路复用模型中,引入了一种新的系统调用,查询IO的就绪状态。在Liunx系统中,对应的系统调用为select/epoll系统调用。通过该系统调用,一个进程可以监视多个文件描述符,一旦某个描述符就绪,内核能够将就绪的状态返回给应用程序。随后,应用程序根据就绪的状态,进行相应的IO系统调用。
优点:与一个线程维护一个连接的阻塞IO模式相比,使用select/epoll的最大有事在于,一个选择器查询线程可以同时处理成千上万个连接。系统不必创建大量的线程,也不必维护这些线程,从而大大减少了系统的开销。
缺点:本质上,select/epoll系统调用是阻塞式的,属于同步IO。都需要在读写时间就绪后,由系统调用本身负责进行读写,也就是说这个读写过程是阻塞的。
异步IO模型
AIO的基本流程是:用户线程通过系统调用,向内核注册某个IO操作。内核在整个IO操作完成后,通知用户程序,用户执行后续的业务操作。
优点:在内核等待数据和复制数据的两个阶段,用户线程都不是咋舌的,用户现成需要接收内核的IO操作完成时间,或者用户线程需要注册一个IO操作完成的回调函数。
缺点:应用线程仅需要进行事件的注册与计收,其余的工作都留给了操作系统,也就是说,需要底层内核提供支持。
本身参考:Netty、Redis、Zookeeper高并发实战尼恩 著
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。