IO多路复用

什么是IO多路复用?就是异步阻塞IO。目的在于提升系统效率。

服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:

(1)同步阻塞IO(Blocking IO):即传统的IO模型。

(2)同步非阻塞IO(Non-blocking IO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。

(3)IO多路复用(IO Multiplexing):即经典的Reactor设计模式,有时也称为异步阻塞IO,Java中的Selector和Linux中的epoll都是这种模型。

(4)异步IO(Asynchronous IO):即经典的Proactor设计模式,也称为异步非阻塞IO。

一、同步和异步

同步和异步的概念描述的是用户线程与内核的交互方式:

同步是指用户线程发起IO请求后需要等待或者轮询内核IO操作完成后才能继续执行;

异步是指用户线程发起IO请求后仍继续执行,当内核IO操作完成后会通知用户线程,或者调用用户线程注册的回调函数。

二、阻塞和非阻塞

阻塞和非阻塞的概念描述的是用户线程调用内核IO操作的方式:

阻塞是指IO操作需要彻底完成后才返回到用户空间;

而非阻塞是指IO操作被调用后立即返回给用户一个状态值,无需等到IO操作彻底完成。

看图比较容易明白。

三、同步阻塞IO

用户需要等待read将socket中的数据读取到buffer后,才继续处理接收的数据。整个IO请求的过程中,用户线程是被阻塞的,这导致用户在发起IO请求时,不能做任何事情,对CPU的资源利用率不够。
在这里插入图片描述

四、同步非阻塞IO

用户线程发起IO请求后,立即返回;但需要不断地调用read,尝试读取socket中的数据,直到读取成功后,才继续处理接收的数据。

虽然用户线程每次发起IO请求后可以立即返回,但是为了等到数据,仍需要不断地轮询、重复请求,消耗了大量的CPU的资源。一般很少直接使用这种模型,而是在其他IO模型中使用非阻塞IO这一特性。
在这里插入图片描述

五、异步阻塞IO(IO多路复用)

异步阻塞模型使用内核提供的select函数(多路分离函数),避免同步非阻塞模型中轮询等待的问题。
在这里插入图片描述
表面上看,异步阻塞模型和同步阻塞模型没有太大的区别,甚至还多了添加监视socket,以及调用select函数的额外操作,效率更差。但是,它最大的优势是可以在一个线程内同时处理多个IO请求:用户可以注册多个socket,然后不断地调用select读取被激活的socket,即可达到在同一个线程内同时处理多个IO请求的目的,所以又叫IO多路复用模型

虽然上述方式允许单线程内处理多个IO请求,但是每个IO请求的过程还是阻塞的(在select函数上阻塞),平均时间甚至比同步阻塞IO模型还要长。如果用户线程只注册自己感兴趣的socket或者IO请求,然后去做自己的事情,等到数据到来时再进行处理,则可以提高CPU的利用率。以下是改良版:
在这里插入图片描述

六、异步非阻塞IO(异步IO)

“真正”的异步IO需要操作系统更强的支持。在IO多路复用模型中,用户线程收到通知后,自行读取数据、处理数据。而在异步IO模型中,则由内核读取数据,并放在缓冲区,用户线程收到通知后,直接使用即可。
在这里插入图片描述

七、异步阻塞IO为什么叫IO多路复用

原因上面已经说了,IO多路复用其实就是异步阻塞IO,就是一个线程,可以同时处理多个IO请求(反过来不成立,一个IO请求只能对应一个线程)。

在这里插入图片描述
其实“I/O多路复用”这个说法之所以难以理解,可能是翻译比较坑爹。所谓的I/O多路复用在英文中其实叫 I/O multiplexing。这里面的 multiplexing 指的是通过跟踪每一个Socket的状态来同时管理多个I/O流。其目的,在于尽量多的提高服务器的吞吐能力。

在这里插入图片描述

八、同步异步、阻塞非阻塞为什么和多线程、IO联系在一起?

线程为什么会和IO扯在一起?

一个线程的执行,通常需要 3 个资源,即CPU,内存和I/O。CPU负责运行,内存负责存放即时数据,I/O负责和磁盘、数据库、网络等做数据交换。

I/O,即输入/输出。Java中,常见的I/O,有文件流,数据库连接,网络连接等。

I/O的特点是每个连接单位时间内只能为一个线程服务,它不像CPU,即使是单核CPU,也可以通过时间切片的方式,执行多线程,多核CPU就更不用说了。IO只能为单一线程服务。还有一个特点是,当一个线程在使用I/O时,一般耗时相对较长,且在这个时间段内,线程不进行计算或读写内存,换言之,线程在使用I/O时,一般不会使用CPU或内存。这个特点很重要,这其实是多线程的重要意义之一。在一个线程使用I/O时,将CPU使用权转移给其它线程,可以更加充分的利用系统资源。

参考文章:
IO多路复用机制详解

多线程与CPU、内存和I/O

IO 多路复用是什么意思?