同步阻塞、同步非阻塞、异步非阻塞三种IO模型

来源: 睡到自然醒
文章作者: 睡到自然醒
文章链接: https://www.lishaojie.top/2020/04/03/nio
本文章著作权归作者所有,任何形式的转载都请注明出处。

同步和异步

同步(Synchronization)和异步(Asynchronous)的方式:同步和异步都是基于应用程序和操作系统处理IO事件所采用的方式。

同步:是应用程序要直接参与IO读写的操作。
异步:所有的IO读写交给操作系统去处理,应用程序只需要等待通知。

同步方式在处理IO事件的时候,必须阻塞在某个方法上面等待我们的IO事件完成(阻塞IO事件或者通过轮询IO事件的方式),对于异步来说,所有的IO读写都交给了操作系统。这个时候,我们可以去做其他的事情,并不需要去完成真正的IO操作,当操作完成IO后,会给我们的应用程序一个通知。

同步的缺陷

阻塞到IO事件,阻塞到read或则write。 这个时候我们就完全不能做自己的事情。让读写方法加入到线程里面,然后阻塞线程来实现,对线程的性能开销比较大。

阻塞和非阻塞

阻塞(Block)和非阻塞(Non-Block):阻塞和非阻塞是进程在访问数据的时候,数据是否准备就绪的一种处理方式。

阻塞:当一个线程调用read()或write()方法时,直到数据被完全读取或写入,此期间不能做任何事。
非阻塞:如果缓冲区的数据没有准备好则直接返回,不会等待。如果数据已经准备好,也直接返回。

BIO

BIO是一种传统的网络通讯模型,同步阻塞IO。谁用谁接收,必须等待数据接收完毕后才能处理业务逻辑。

它其实就是服务端创建一个ServerSocket, 然后客户端用一个Socket去连接服务端的ServerSocket, ServerSocket接收到了一个的连接请求就创建一个Socket和一个线程去跟客户端的Socket进行通讯。接着客户端和服务端就进行阻塞式的通信,客户端发送一个请求,服务端Socket进行处理后返回响应。在响应返回前,客户端那边就阻塞等待,什么事情也做不了。

BIO流程图

BIO流程图

采用BIO通信模型的服务端,通常由一个独立的Acceptor线程负责监听客户端的连接,接收到客户端连接之后为客户端连接创建一个新的线程处理请求消息,处理完成之后,返回应答消息给客户端,线程销毁,这就是典型的一请求一应答模型(Acceptor)。

这种方式的缺点:每次一个客户端接入,都需要在服务端创建一个线程来服务这个客户端。这样大量客户端来的时候,就会造成服务端的线程数量可能达到了几千甚至几万,这样就可能会造成服务端过载过高,最后崩溃死掉。

NIO

NIO是一种同步非阻塞IO,基于Reactor模型实现。(反应堆)

其实相当于就是一个线程处理大量的客户端的请求,通过一个线程轮询大量的channel,每次就获取一批有事件的channel,然后对每个请求启动一个线程处理即可。

NIO流程图

NIO流程图

NIO的核心就是非阻塞,就是用一个selector线程就可以不停轮询channel,所有客户端请求都不会阻塞,面向缓冲区,不需要等待,直接就可以进来,大不了就是等待一会排下队而已。

NIO相较于BIO优化的核心是,一个客户端并不是时时刻刻都有数据进行交互,没有必要死耗着一个线程不放,所以客户端选择了让线程歇一歇,只有客户端有相应的操作的时候才发起通知,创建一个线程来处理请求。

AIO

AIO是一种异步非阻塞IO,基于Proactor模型实现。

每个连接发送过来的请求,都会绑定一个Buffer,然后通知操作系统去完成异步的读,这个时间你就可以去做其他的事情,等到操作系统完成读之后,就会调用你的接口,给你操作系统异步读完的数据。这个时候你就可以拿到数据进行处理,将数据往回写。在往回写的过程,同样是给操作系统一个Buffer,让操作系统去完成写,写完了来通知你。这俩个过程都有buffer存在,数据都是通过buffer来完成读写。这里面的主要的区别在于将数据写入的缓冲区后,就不去管它,剩下的去交给操作系统去完成。操作系统写回数据也是一样,写到Buffer里面,写完后通知客户端来进行读取数据。

AIO流程图

AIO流程图

来源: 睡到自然醒
文章作者: 睡到自然醒
文章链接: https://www.lishaojie.top/2020/04/03/nio
本文章著作权归作者所有,任何形式的转载都请注明出处。