Java高并发教程:高并发IO的底层原理

huangzonggui 2020-06-04

Java高并发教程:高并发IO的底层原理

IO读写的基础原理

程序进行IO读写依赖于操作系统底层的IO读写,主要为read、write两大系统调用。在不同的操作系统中,IO读写的系统调用的名称可能不完全一样,但是基本功能是一样的。

首先我们必须要明白的的是,read系统调用,并不是直接从物理设备把数据读取到内存中;write系统调用,也不是直接把数据写入到物理设备。上层应用无论时调用操作系统的read,还是write都会涉及缓存区。即,调用read,是把数据从内核缓存区复制到进程缓存区,wirte是把数据从进程缓存区复制到内核缓存区。

所以,程序的IO操作实际上是缓存的复制,并不是实际物理设备的读写,这项底层的读写交换,是由操作系统内核(Kernel)来完成的。

操作系统基础知识:

1.操作系统与外部设备之间:主要通过中断机制来实现。

2.操作系统与上层应用程序:主要通过异常与系统调用两个机制来实现。

内核缓存区与进程缓存区

缓存的目的是减少频繁地与设备之间的物理交换,因为外部设备的直接读写,都需要操作系统中断,而中断耗时耗力,所以缓存很有必要

  • 在Linux系统中,操作系统内核只有一个内核缓冲区
  • 每个用户程序(进程),有自己独立的缓存区,叫做进程缓存区

用户程序的IO读写程序,在大多数情况下,并没有进行实际的IO操作,而是在进程缓冲区和内核缓冲区之间直接进行数据的交换。

系统调用read&write的流程

到这里,还是需要举个例子:

Java高并发教程:高并发IO的底层原理

比如在Java服务器端,完成一次socket请求和响应,完整的流程如下:·

  1. 客户端请求:Linux通过网卡读取客户端的请求数据,将数据读取到内核缓冲区。·
  2. 获取请求数据:Java服务器通过read系统调用,从Linux内核缓冲区读取数据,再送入Java进程缓冲区。·
  3. 服务器端业务处理:Java服务器在自己的用户空间中处理客户端的请求。
  4. 服务器端返回数据:Java服务器完成处理后,构建好的响应数据,将这些数据从用户缓冲区写入内核缓冲区。这里用到的是write系统调用。·
  5. 发送给客户端:Linux内核通过网络IO,将内核缓冲区中的数据写入网卡,网卡通过底层的通信协议,会将数据发送给目标客户端。

四种主要的IO模型

1.同步阻塞IO(Blocking IO)

阻塞IO指的是需要内核IO操作彻底完成后,才返回到用户空间执行用户的操作

同步IO指的是用户空间的线程是主动发起IO请求的一方,内核空间是被动接收方。异步IO则反过来,是指系统内核是主动发起IO请求的一方,用户空间的线程是被动接受方。

2.同步非阻塞IO(Non-blocking IO)

非阻塞IO,指的是用户空间的程序不需要等待内核IO操作彻底完成,可以立即返回用户空间执行用户的操作,即处于非阻塞的状态,与此同时内核会立即返回给用户一个状态值。

简单来说:阻塞是指用户空间(调用线程)一直在等待,而不能干别的事情非阻塞是指用户空间(调用线程)拿到内核返回的状态值就返回自己的空间,IO操作可以干就干,不可以干,就去干别的事情。

注意:这里所说的NIO(同步非阻塞IO)模型,并非Java的NIO(New IO)库。

3.IO多路复用(IO Multiplexing)

IO多路复用可以解决非阻塞IO模型中存在的轮询等待问题。

4.异步IO(Asynchronous IO)

相关推荐