当前位置: 首页 > news >正文

那些年让你迷惑的阻塞、非阻塞、异步、同步

那些年让你迷惑的阻塞、非阻塞、异步、同步

作者:milter 链接: https://www.jianshu.com/p/3d603166f54d
 
 

在IT圈混饭吃,不管你用什么编程语言、从事前端还是后端,阻塞、非阻塞、异步、同步这些概念,都需要清晰地掌握,否则,怎么与面试官谈笑风生(chui niu pi)?但是,掌握这些概念又不是非常容易,尤其对非科班出身的,更加困难。本文试图给出一个清晰简明但不失深刻的介绍,希望对大家有所帮助。

1、从I/O说起

这些概念之所以容易令人迷惑,在于很多人对I/O就没有清晰准确的理解,后面的理解自然不可能正确。我想用一个具体的例子来说明一下I/O。

设想自己是一个进程,就叫小进吧。小进需要接收一个输入,我们不管这个输入是从网络套接字来,还是键盘,鼠标来,输入的来源可以千千万万。但是,都必须由内核来帮小进完成,为啥内核这么霸道?因为计算机上运行的可不只是咱小进一个进程,还有很多进程。这些进程兄弟也可能需要从这些输入设备接收输入,没有内核居中协调,岂不是乱套。

从小进的角度看,内核帮助它完成输入,其实包括三个步骤:

  • 1、内核替小进接收好数据,这些数据暂时存在内核的内存空间

  • 2、内核将数据从自己的内存空间复制到小进的内存空间

  • 3、告诉小进,输入数据来了,赶快读吧

这三步看似挺简单,其实在具体实现时,有很多地方需要考虑:

  • 0、小进如何告诉内核自己要接收一个输入?

  • 1、内核接到小进的请求,替小进接收好数据这段时间, 小进咋办?

  • 2、内核在将数据复制到小进的内存空间这段时间,小进咋办?

  • 3、到底什么时候告诉小进数据准备好了,是在内核接收好数据之后就告诉小进,还是在将数据复制到小进的内存空间之后再告诉他?

  • 4、内核以什么样的方式告诉小进,数据准备好了?

2、阻塞式I/O模型

对上面5个问题,最简单的解决方案就是阻塞式I/O模型,它的过程是这样的:

小进:内核内核,我要接收一个键盘输入,快点帮我完成!

内核:好咧!biubiu!一个阻塞丢给小进,小进顿时石化,就像被孙悟空点了定一样。

就这样,小进在石化中,时间一点点流逝。终于,内核收到了数据。

内核:数据终于来了,我要开干了!duang duang duang,先把数据存在自己的内核空间,然后又复制到小进的用户空间。

内核:biubiu!一个解除阻塞丢给小进,小进瞬间复活,小进的记忆还是停留在让内核帮他接收输入时。

小进:哇!内核真靠谱,数据已经有了!干活去!

我们可以看到,小进发出接收输入的请求给内核开始,就处于阻塞状态,直到内核将数据复制到小进的用户空间,小进才解除阻塞。

3、非阻塞式I/O

小进发现,阻塞式I/O中,自己总要被阻塞好久,好不爽啊,于是小进改用了非阻塞式I/O,其过程是这样的:

小进:内核内核,我要接收一个输入,赶紧帮我看看,数据到了没有,先说好,不要阻塞我。

内核:查看了一下自己的内核空间,没有发现数据,于是迅速告诉小进,没有呢!并继续帮小进等着数据。

如此这样,小进不断地问内核,终于,过了一段时间,小进再一次询问时,内核往自己的空间中一查,呦!数据来了,不胜其烦的内核迅速告诉小进,数据好了!

小进:快给我!

内核:biu!一个阻塞丢给小进,悲催的小进还是石化了!

内核赶紧将自己空间的输入数据复制到小进的用户空间,复制好后。

内核:biu!一个非阻塞丢给小进,小进立马复活

小进:哇!数据来了,啥也不说,干活!

我们看到,所谓的非阻塞I/O,其实在内核将数据从内核空间复制到小进的用户空间时,小进还是被阻塞的。

4、信号驱动式I/O

非阻塞I/O中,小进不停地问内核,数据好了没有啊,内核感觉太烦了,于是想出一个好办法。

内核告诉小进,本内核升级了,如果想要我替你接收输入,请先注册一个信号处理函数,等数据准备好时,我会发信号给你。于是,现在的流程是这样的:

小进:注册信号处理函数,告诉内核,自己要接收一个输入,然后继续干活!

内核:收到函数,开始执行数据接收

接收完成时,给小进发送信号,信号处理函数收到信号,开始向内核发送读数据请求

内核:biu!阻塞了小进,并把数据从内核空间复制到小进的用户空间。

内核:biu!解除了阻塞

小进:哇!数据来了!啥也不说,干活去!

5、异步I/O

上面的三种I/O解决方案中,小进都被阻塞了,只不过是阻塞时间长短不一样,第一种方案中小进被阻塞的时间长一些,在内核接收数据以及将数据复制到小进的用户空间时,都被阻塞。

第二、第三种方案中,只在内核将数据从内核空间复制到小进的用户空间时,小进才被阻塞。

我们现在说的异步I/O,目的就是让小进绝对不被阻塞。其过程是这样的:

小进:内核内核,我要接收一个输入,弄好了告诉我。同时将一个信号和信号处理函数告诉内核,然后继续干自己的活了。

内核:得了您嘞,您先忙。

一直到内核接收到数据并将数据从内核空间复制到小进的用户空间后,内核才给小进发送信号。小进在信号处理函数中可以直接处理数据。

6、那啥是同步呢?

一句话,凡是让小进阻塞(不管长短)的I/O方案都是同步I/O。也就是说,阻塞、非阻塞、信号驱动式都是同步I/O。

7、无总结,不进步

上面,我们从完成输入时,进程与内核的交互方式的角度分析了不同的I/O解决方案,在这个过程中,解释清楚了阻塞、非阻塞、同步、异步的概念。

 

相关文章:

  • Cloudopt-logger — Kotlin 实现的日志框架扩展
  • Linux日记本_04:阿里云ECS服务器(CentOS7)端口设置以及 MySQL数据库搭建
  • [js]- 两个对象的合并(Object.assign)
  • 火币交易细则
  • 阿里云服务器配置过程
  • redirectTo、navigateTo与switchTap区别
  • python3 猜数字小游戏2.0
  • python函数式编程一
  • .NET性能优化(文摘)
  • CentOS 7.5 运维之路之网络配置
  • Linux日志分析详解
  • 高德地图大批量数据(上万)画历史轨迹实现方案
  • java并发包
  • 爬取伯乐在线文章(二)通过xpath提取源文件中需要的内容
  • yum工具介绍及本地源配置方法
  • (三)从jvm层面了解线程的启动和停止
  • Android开发 - 掌握ConstraintLayout(四)创建基本约束
  • Docker入门(二) - Dockerfile
  • Laravel Mix运行时关于es2015报错解决方案
  • Magento 1.x 中文订单打印乱码
  • PHP 小技巧
  • Python socket服务器端、客户端传送信息
  • React-Native - 收藏集 - 掘金
  • sessionStorage和localStorage
  • Vue官网教程学习过程中值得记录的一些事情
  • 前端 CSS : 5# 纯 CSS 实现24小时超市
  • 手机端车牌号码键盘的vue组件
  • 无服务器化是企业 IT 架构的未来吗?
  • 掌握面试——弹出框的实现(一道题中包含布局/js设计模式)
  • scrapy中间件源码分析及常用中间件大全
  • "无招胜有招"nbsp;史上最全的互…
  • #### go map 底层结构 ####
  • #每天一道面试题# 什么是MySQL的回表查询
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • #我与Java虚拟机的故事#连载13:有这本书就够了
  • (4)事件处理——(6)给.ready()回调函数传递一个参数(Passing an argument to the .ready() callback)...
  • (delphi11最新学习资料) Object Pascal 学习笔记---第7章第3节(封装和窗体)
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (附源码)ssm跨平台教学系统 毕业设计 280843
  • (规划)24届春招和25届暑假实习路线准备规划
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (生成器)yield与(迭代器)generator
  • (十三)Flask之特殊装饰器详解
  • (转)VC++中ondraw在什么时候调用的
  • (转)创业家杂志:UCWEB天使第一步
  • (转)项目管理杂谈-我所期望的新人
  • .NET 中 GetProcess 相关方法的性能
  • .Net8 Blazor 尝鲜
  • /etc/sudoers (root权限管理)
  • @开发者,一文搞懂什么是 C# 计时器!
  • [ element-ui:table ] 设置table中某些行数据禁止被选中,通过selectable 定义方法解决
  • [20160807][系统设计的三次迭代]
  • [20170728]oracle保留字.txt
  • [2023-年度总结]凡是过往,皆为序章
  • [CF]Codeforces Round #551 (Div. 2)