5种IO流

2023-11-18


在《Unix网络编程》一书中提到了五种IO模型,分别是:阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO

下面就分别来介绍一下这5种IO模型的异同。

1.阻塞IO模型

  最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。

  当用户线程发出IO请求之后,内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。

典型的阻塞IO模型的例子为:

data = socket.read();

如果数据没有就绪,就会一直阻塞在read方法。

2.非阻塞IO模型

  当用户线程发起一个read操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。

  所以事实上,在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU

典型的非阻塞IO模型一般如下:

while(true){

   data = socket.read();

   if(data!= error){

       处理数据

       break;

   }

}

  但是对于非阻塞IO就有一个非常严重的问题,在while循环中需要不断地去询问内核数据是否就绪,这样会导致CPU占用率非常高,因此一般情况下很少使用while循环这种方式来读取数据。

3.多路复用IO模型

  多路复用IO模型是目前使用得比较多的模型。Java NIO实际上就是多路复用IO

  在多路复用IO模型中,会有一个线程不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。

  在Java NIO中,是通过selector.select()去查询每个通道是否有到达事件,如果没有事件,则一直阻塞在那里,因此这种方式会导致用户线程的阻塞。

  也许有朋友会说,我可以采用多线程+ 阻塞IO 达到类似的效果,但是由于在多线程 阻塞IO 中,每个socket对应一个线程,这样会造成很大的资源占用,并且尤其是对于长连接来说,线程的资源一直不会释放,如果后面陆续有很多连接的话,就会造成性能上的瓶颈。

  而多路复用IO模式,通过一个线程就可以管理多个socket,只有当socket真正有读写事件发生才会占用资源来进行实际的读写操作。因此,多路复用IO比较适合连接数比较多的情况。

  另外多路复用IO为何比非阻塞IO模型的效率高是因为在非阻塞IO中,不断地询问socket状态时通过用户线程去进行的,而在多路复用IO中,轮询每个socket状态是内核在进行的,这个效率要比用户线程要高的多。

  不过要注意的是,多路复用IO模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用IO模型来说,一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。

4.信号驱动IO模型

  在信号驱动IO模型中,当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用IO读写操作来进行实际的IO请求操作。这个一般用于UDP中,对TCP套接口几乎是没用的,原因是该信号产生得过于频繁,并且该信号的出现并没有告诉我们发生了什么事情

5.异步IO模型

  异步IO模型才是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个asynchronous read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要关心实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。

  也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的,在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作。

  注意,异步IO是需要操作系统的底层支持,在Java 7中,提供了Asynchronous IO。简称AIO

前面四种IO模型实际上都属于同步IO,只有最后一种是真正的异步IO,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

两种高性能IO设计模式

在传统的网络服务设计模式中,有两种比较经典的模式:

  一种是多线程,一种是线程池。

  对于多线程模式,也就说来了client,服务器就会新建一个线程来处理该client的读写事件,如下图所示:

这种模式虽然处理起来简单方便,但是由于服务器为每个client的连接都采用一个线程去处理,使得资源占用非常大。因此,当连接数量达到上限时,再有用户请求连接,直接会导致资源瓶颈,严重的可能会直接导致服务器崩溃。

  因此,为了解决这种一个线程对应一个客户端模式带来的问题,提出了采用线程池的方式,也就说创建一个固定大小的线程池,来一个客户端,就从线程池取一个空闲线程来处理,当客户端处理完读写操作之后,就交出对线程的占用。因此这样就避免为每一个客户端都要创建线程带来的资源浪费,使得线程可以重用。

  但是线程池也有它的弊端,如果连接大多是长连接,因此可能会导致在一段时间内,线程池中的线程都被占用,那么当再有用户请求连接时,由于没有可用的空闲线程来处理,就会导致客户端连接失败,从而影响用户体验。因此,线程池比较适合大量的短连接应用。

  因此便出现了下面的两种高性能IO设计模式:ReactorProactor

Reactor模式中,会先对每个client注册感兴趣的事件,然后有一个线程专门去轮询每个client是否有事件发生,当有事件发生时,便顺序处理每个事件,当所有事件处理完之后,便再转去继续轮询,如下图所示:

从这里可以看出,上面的五种IO模型中的多路复用IO就是采用Reactor模式。注意,上面的图中展示的 是顺序处理每个事件,当然为了提高事件处理速度,可以通过多线程或者线程池的方式来处理事件。Java NIO使用的就是这种

  在Proactor模式中,当检测到有事件发生时,会新起一个异步操作,然后交由内核线程去处理,当内核线程完成IO操作之后,发送一个通知告知操作已完成,可以得知,异步IO模型采用的就是Proactor模式。Java AIO使用的这种,转载注明来自:http://www.youxijishu.com/h-nd-141-2_323.html


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

5种IO流 的相关文章

  • Java学习--JDBC操作数据库(直析操作)

    1 了解JDBC的常用类和接口 DriverManager类 用来管理数据库中的所有驱动程序 Connection接口 代表与特定的数据库的连接 Statement接口 用于创建向数据库中传递SQL语句的对象 PreparedStateme
  • -day25--mysql入门

    第四模块 MySQL数据库 数据库管理系统 DBMS 专注于帮助开发者解决数据存储的问题 这样开发者就可以把主要精力放在实现业务功能上了 业内有很多的的数据库管理系统产品 例如 MySQL 原来是sun公司 后来被甲骨文收购 现在互联网企业
  • 排序算法(java版本)

    1 直接插入排序 1 基本思想 在要排序的一组数中 假设前面 n 1 n gt 2 个数已经是排 好顺序的 现在要把第n个数插到前面的有序数中 使得这n个数 也是排好顺序的 如此反复循环 直到全部排好顺序 2 实例 3 用java实现 pa
  • 严重性 代码 说明 项目 文件 行 禁止显示状态 错误 LNK2038 检测到“RuntimeLibrary”的不匹配项: 值“MD_DynamicRelease”不匹配值“MDd_DynamicDe

    系列文章目录 文章目录 系列文章目录 前言 一 错误原因 二 解决问题 在这里插入图片描述 https img blog csdnimg cn a8ce751feae54668aa54ffe2e0031560 png 前言 严重性 代码 说
  • 2023年网络安全考试试题,背下来通过率99%

    1 关于数据使用说法错误的是 A 在知识分享 案例中如涉及客户网络数据 应取敏感化 不得直接使用 B 在公开场合 公共媒体等谈论 传播或发布客户网络中的数据 需获得客户书面授权或取敏感化 公开渠道获得的除外 C 客户网络数据应在授权范围内使
  • clang+llvm+linux x86平台交叉编译arm64

    下载工具链 bin bash workPATH pwd toolchain mkdir p workPATH cd workPATH URL LLVM https github com llvm llvm project releases
  • 算法训练营第十一天(7.22)

    目录 LeeCode20 Valid Parentheses LeeCode1047 Remove All Adjacent Duplicates In String LeeCode150 Evaluate Reverse Polish N
  • 第三章 3.1节练习 & 3.2.2节练习

    练习3 1 使用恰当的using声明重做1 4 1节 11页 和2 6 2节 67页 的练习 解答 这里就不写代码了 因为可以using命名空间或者空间中的对应函数 可以出现很多种组合 可以按照自己喜欢或熟悉的方式来写 练习3 2 编写一段
  • python 面向对象 超级详细全面讲解

    如有错误 欢迎留言指出讨论 1 面向对象和面向过程 1 1 面向过程注重的是结果 从结果出发去考虑问题的实现步骤 1 2 面向对象注重的是设计 从现实生活的角度 从设计的角度去考虑问题的实现步骤 1 3 虽然2种思想的目的都是为了做出一个程
  • 00后视频审核员,3个月顺利转行车载测试,他说你也能行!

    21年夏天毕业后 自觉比较社恐的我去找了一份看似清闲又不用和逼人打交道太多的工作 原本以为这份工作会成为我的庇佑所 没想到也是一地鸡毛 是的 我是一个视频审核 顾名思义 作为一个视频审核员 毫无疑问我的工作就是看视频 也许有人会说 就看看视
  • numpy中np.array()功能

    功能 将数据转化为矩阵 a 1 2 3 4 5 6 7 8 9 b np array a c np asarray a a 2 1 print a print b print c 从中我们可以看出np array与np asarray功能是
  • JAVA并发队列

    Java并发队列 在并发队列上JDK提供了两套实现 一个是以ConcurrentLinkedQueue为代表的高性能队列 一个是以BlockingQueue接口为代表的阻塞队列 无论哪种都继承自Queue 一 ConcurrentLinke
  • 【Hbase 05】Hbase表的设计原则与优化方案

    这里说一下Hbase在使用过程中的表设计原则与优化方案 如果你是运维或者开发兼顾环境的工作 也许比较受用 话不多说 我们直接开始说优化的内容 一 表设计原则 1 行键设计 行键在设计的时候要尽量的散列 例如可以考虑使用哈希 加密算法等使结果
  • 在Webpack 5 中如何进行 CSS 常用配置?

    本文摘要 主要通过实操讲解运用Webpack 5 CSS常用配置的方法步骤 前文已谈到可以通过配置 css loader 和 style loader 使 webpack5 具有处理 CSS 资源的能力 css loader 首先会分析出各
  • 【线性代数】向量组的线性相关性

    文章目录 向量组及其线性组合 一 向量 二 线性表示 1 线性组合的定义 2 线性表示的定义 3 线性表示的充要条件 三 向量组等价 1 向量组等价定义 2 向量组线性表示的充要条件 3 向量组等价的充要条件 4 向量组线性表示的必要条件
  • 如何设计企业节点的『工业互联网标识解析系统』

    一 星火 链网 体系架构 星火 链网 以节点形式进行组织互联互通 其中包括三类节点 超级节点 骨干节点 业务节点 其底层采用 1 N 主从链群架构 支持同构和异构区块链接入主链 在全国重点区域部署 星火 链网 超级节点 作为国家链网顶层 提
  • Waffle使用初体验

    一 什么是Waffle Waffle是什么呢 我们直接看其文档上的介绍 Waffle is a library for writing and testing smart contracts Sweeter simpler and fast
  • 主要进行OGRE引擎和shader

    今天 老大告诉我 只要把GLSL进行就行了 其余不用管 那就与OGRE相结合 轮流进行即可 看看引擎架构 搞搞shader
  • HDC即将开始,有哪些亮点值得期待?

    鸿蒙新版本即将发布 开发者该如何紧跟生态热点 最重磅的当然是HarmonyOS 3 1beta版本将于11月4日在华为开发者大会2022 HDC 现场宣布发布 代表着鸿蒙生态新的征程 除正式发布外 最近华为开发者学堂已经上线的一些鸿蒙生态相

随机推荐

  • 北大硕士7年嵌入式学习经验分享

    01 前言 大家现在状态是怎么样的 这几年技术进步怎么样 职场晋升 管理水平有没有提升 欢迎留言 本文内容来自于知乎 觉得内容很不错 分享给大家 下文的我代表的是原作者 作者 梦人亦冷 链接 https www zhihu com ques
  • 数据库查询语句

    数据库查询语句无疑是所有语句中 最重要的语句 经常配合where一起使用 1 最基本的查询 公式1 select from 表名 查看aaa表中的所有数据 SELECT FROM aaa 你说 我不想查看表中所有的数据 我就想查看表中id字
  • Python进行大数据挖掘和分析

    大数据无处不在 在时下这个年代 不管你喜欢与否 在运营一个成功的商业的过程中都有可能会遇到它 什么是大数据 大数据就像它看起来那样 有大量的数据 单独而言 你能从单一的数据获取的洞见穷其有限 但是结合复杂数学模型以及强大计算能力的TB级数据
  • 中国大陆网站TOP100

    1 新浪新闻中心 包括即日的国内外不同类型的新闻与评论 人物专题 图库 BR www sina com cn 2 Baidu com 全球最大中文搜索引擎 向人们提供简单 可依赖的信息获取方式 BR www baidu com 3 搜狐 资
  • VMware Vsphere-下

    18 创建资源池和vAPPs 主机右击可以看到 新建资源池 资源池里可以指定资源池所消耗的物理的cpu和内存 份额 预留 限制 资源池里面可以放虚拟机 资源池的作用 可以将几台虚拟机放进一个池 限制资源 这样就不会出现一个虚拟机抢占过多资源
  • vue3知识点:Suspense组件

    文章目录 五 新的组件 3 Suspense 案例 完整代码 本人其他相关文章链接 五 新的组件 3 Suspense 等待异步组件时渲染一些额外内容 让应用有更好的用户体验 使用步骤 第1步 异步引入组件 import defineAsy
  • 记录移动开发初探——用uniApp+sqlite仿XyKey实现密码管理记事本

    写在前面 最近刚准备上手移动开发 本着想要多端可用的原则 了解到了uniApp 大致扫完一遍文档 基本可以算是vue 微信小程序原生 对我来说基本0难度可直接进入开发 因此想着索性做一款简单的app来做更加深入的了解 就在这时候 朋友给我推
  • 在vscode中做实验出现的bug......

    1 python如何调用opencv中的saliency模块 如果你已经安装了opencv python的库 但是调用cv2 saliency方法时出现了如下的报错 module cv2 saliency has no attribute
  • (数据库链接池)spring内容复习7月16日笔记

    2023 07 16数据库连接池 数据库连接池是个容器 负责分配 管理数据库连接对象 Connection 它允许应用程序重复使用一个现有的数据库链接 而不是在重新建立一个 而且释放空闲时间超过最大空闲时间的链接 来避免因为没有释放链接而引
  • unity 设置image透明度_Unity透明效果-透明度测试

    在之前的记录中已经知道了透明度测试的原理 本节主要就在Unity中通过透明度测试实现透明效果进行实践 原理回顾 透明度测试采用一种 非舍即留 的机制 即 若某片元的透明度不满足条件 通常小于某个阈值 则舍弃 否则就按照不透明物体去处理 也就
  • unity 多人同屏处理

    一 把fbx的Optimize GameObject勾选上 会优化你模块的面数 不过好像有可能会引起别的问题 优化后和代码上的mesh数据对不上造成bug 二 由于每个sinnedmesh会产生一个drawcall 所以多人同屏时就会卡 针
  • SED系列教程

    1 易百 Sed教程 http www yiibai com sed sed branches html
  • vi指令的基本使用

    一 vi的基本概念 基本上vi可以分为三种状态 分别是命令模式 command mode 插入模式 Insert mode 和底行模式 last line mode 各模式的功能区分如下 1 命令行模式command mode 控制屏幕光标
  • unexpected EOF while parsing是什么意思

    unexpected EOF while parsing 意思是在解析的过程中遇到了意外的文件结束符 这通常表示程序的代码有语法错误 导致程序无法正常运行 这个错误的具体原因可能有很多 比如 在字符串中使用了单引号或双引号 但没有正确地将它
  • Linux 搭建 JumpServer 堡垒机

    跳板机概述 跳板机就是一台服务器 开发或运维人员在维护过程中首先要统一登录到这台服务器 然后再登录到目标设备进行维护和操作 跳板机缺点 没有实现对运维人员操作行为的控制和审计 使用跳板机的过程中还是会出现误操作 违规操作导致的事故 一旦出现
  • python下载文件暂停恢复_新技能 get —— Python 断点续传下载文件

    原博文 2017 03 24 12 44 from urllib request import urlretrieve import sys import os prev reported download percent None 首先定
  • Java复习-25-单例设计模式

    单例设计模式 目的 使用场景 在实际开发下 会存在一种情况 某一种类在程序的整个生命周期中 只需要实例化一次就足够了 例如 系统数据类 由于操作系统只有一个 因此在程序初始化时该类只需要实例化一次 之后的系统数据更改都是在这一个实例化对象中
  • sha256是什么算法,sha256的安全性,sha256算法详解

    一些朋友对密码学方面的知识不是很了解 什么sha1 sha256 sha512等等 这么多算法类似的算法可能会有一点混淆 尤其是对sha256不是很理解 本文整合了一些关于sha256的相关资料 针对sha256是什么算法 它的安全性如何
  • SSM商城项目实战:订单管理

    SSM商城项目实战 订单管理 在SSM商城项目中 订单管理是一个非常重要的功能模块 本文将详细介绍订单管理的实现思路和步骤代码 实现SSM商城项目中订单管理功能的思路如下 设计数据库表结构 根据订单管理的需求 设计订单表和订单明细表的结构
  • 5种IO流

    在 Unix网络编程 一书中提到了五种IO模型 分别是 阻塞IO 非阻塞IO 多路复用IO 信号驱动IO以及异步IO 下面就分别来介绍一下这5种IO模型的异同 1 阻塞IO模型 最传统的一种IO模型 即在读写数据过程中会发生阻塞现象 当用户