cpu 被挂起和阻塞_迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章...

334bf012e52bae744646c7b3fe0734fd.png
网上有很多讲同步/异步/阻塞/非阻塞/BIO/NIO/AIO的文章,但是都没有达到我的心里预期,于是自己写一篇出来。

常规的误区

假设有一个展示用户详情的需求,分两步,先调用一个HTTP接口拿到详情数据,然后使用适合的视图展示详情数据。
如果网速很慢,代码发起一个HTTP请求后,就卡住不动了,直到十几秒后才拿到HTTP响应,然后继续往下执行。
这个时候你问别人,刚刚代码发起的这个请求是不是一个同步请求,对方一定回答是。这是对的,它确实是。
但你要问它为什么是呢?对方一定是这样回答的,“因为发起请求后,代码就卡住不动了,直到拿到响应后才可以继续往下执行”。
我相信很多人也都是这样认为的,其实这是不对的,是把因果关系搞反了:
不是因为代码卡住不动了才叫同步请求,而是因为它是同步请求所以代码才卡住不动了。
至于为什么能卡住不动,这是由操作系统和CPU决定的:
因为内核空间里的对应函数会卡住不动,造成用户空间发起的系统调用卡住不动,继而使程序里的用户代码卡住不动了。
因此卡住不动了只是同步请求的一个副作用,并不能用它来定义同步请求,那该如何定义呢?

同步和异步

所谓同步,指的是协同步调。既然叫协同,所以至少要有2个以上的事物存在。协同的结果就是:
多个事物不能同时进行,必须一个一个的来,上一个事物结束后,下一个事物才开始。
那当一个事物正在进行时,其它事物都在干嘛呢?
严格来讲这个并没有要求,但一般都是处于一种“等待”的状态,因为通常后面事物的正常进行都需要依赖前面事物的结果或前面事物正在使用的资源。
因此,可以认为,同步更希望关注的是从宏观整体来看,多个事物是一种逐个逐个的串行化关系,绝对不会出现交叉的情况。
所以,自然也不太会去关注某个瞬间某个具体事物是处于一个什么状态。
把这个理论应用的出神入化的非“排队”莫属。凡是在资源少需求多的场景下都会用到排队。
比如排队买火车票这件事:
其实售票大厅更在意的是旅客一个一个的到窗口去买票,因为一次只能卖一张票。
即使大家一窝蜂的都围上去,还是一次只能卖一张票,何必呢?挤在一起又不安全。
只是有些人素质太差,非要往上挤,售票大厅迫不得已,采用排队这种形式来达到自己的目的,即一个一个的买票。
至于每个旅客排队时的状态,是看手机呀还是说话呀,根本不用去在意。

除了这种由于资源导致的同步外,还存在一种由于逻辑上的先后顺序导致的同步。
比如,先更新代码,然后再编译,接着再打包。这些操作由于后一步要使用上一步的结果,所以只能按照这种顺序一个一个的执行。
关于同步还需知道两个小的点:
一是范围,并不需要在全局范围内都去同步,只需要在某些关键的点执行同步即可。
比如食堂只有一个卖饭窗口,肯定是同步的,一个人买完,下一个人再买。但吃饭的时候也是一个人吃完,下一个人才开始吃吗?当然不是啦。
二是粒度,并不是只有大粒度的事物才有同步,小粒度的事物也有同步。

只不过小粒度的事物同步通常是天然支持的,而大粒度的事物同步往往需要手工处理。
比如两个线程的同步就需要手工处理,但一个线程里的两个语句天然就是同步的。
所谓异步,就是步调各异。既然是各异,那就是都不相同。所以结果就是:
多个事物可以你进行你的、我进行我的,谁都不用管谁,所有的事物都在同时进行中。

一言以蔽之,同步就是多个事物不能同时开工,异步就是多个事物可以同时开工。

注:一定要去体会“多个事物”,多个线程是多个事物,多个方法是多个事物,多个语句是多个事物,多个CPU指令是多个事物。等等等等。

阻塞和非阻塞

所谓阻塞,指的是阻碍堵塞。它的本意可以理解为由于遇到了障碍而造成的动弹不得。

所谓非阻塞,自然是和阻塞相对,可以理解为由于没有遇到障碍而继续畅通无阻。
对这两个词最好的诠释就是,当今中国一大交通难题,堵车:
汽车可以正常通行时,就是非阻塞。一旦堵上了,全部趴窝,一动不动,就是阻塞。

因此阻塞关注的是不能动,非阻塞关注的是可以动。

不能动的结果就是只能等待,可以动的结果就是继续前行。
因此和阻塞搭配的词一定是等待,和非阻塞搭配的词一定是进行。
回到程序里,阻塞同样意味着停下来等待,非阻塞表明可以继续向下执行。

阻塞和等待

等待只是阻塞的一个副作用而已,表明随着时间的流逝,没有任何有意义的事物发生或进行。

阻塞的真正含义是你关心的事物由于某些原因无法继续进行,因此让你等待。但没必要干等,你可以做一些其它无关的事物,因为这并不影响你对相关事物的等待。
在堵车时,你可以干等。也可以玩手机、和别人聊天,或者打牌、甚至先去吃饭都行。因为这些事物并不影响你对堵车的等待。不过你的车必须呆在原地。
在计算机里,是没有人这么灵活的,一般在阻塞时,选在干等,因为这最容易实现,只需要挂起线程,让出CPU即可。在条件满足时,会重新调度该线程。

两两组合

所谓同步/异步,关注的是能不能同时开工。
所谓阻塞/非阻塞,关注的是能不能动。
通过推理进行组合:
同步阻塞,不能同时开工,也不能动。只有一条小道,一次只能过一辆车,可悲的是还TMD的堵上了。
同步非阻塞,不能同时开工,但可以动。只有一条小道,一次只能过一辆车,幸运的是可以正常通行。
异步阻塞,可以同时开工,但不可以动。有多条路,每条路都可以跑车,可气的是全都TMD的堵上了。
异步非阻塞,可以工时开工,也可以动。有多条路,每条路都可以跑车,很爽的是全都可以正常通行。
是不是很容易理解啊。其实它们的关注点是不同的,只要搞明白了这点,组合起来也不是事儿。
回到程序里,把它们和线程关联起来:
同步阻塞,相当于一个线程在等待。
同步非阻塞,相当于一个线程在正常运行。
异步阻塞,相当于多个线程都在等待。
异步非阻塞,相当于多个线程都在正常运行。

I/O

IO指的就是读入/写出数据的过程,和等待读入/写出数据的过程。一旦拿到数据后就变成了数据操作了,就不是IO了。
拿网络IO来说,等待的过程就是数据从网络到网卡再到内核空间。读写的过程就是内核空间和用户空间的相互拷贝。

所以IO就包括两个过程,一个是等待数据的过程,一个是读写(拷贝)数据的过程。而且还要明白,一定能包括操作数据的过程。

阻塞IO和非阻塞IO

应用程序都是运行在用户空间的,所以它们能操作的数据也都在用户空间。按照这样子来理解,只要数据没有到达用户空间,用户线程就操作不了。

如果此时用户线程已经参与,那它一定会被阻塞在IO上。这就是常说的阻塞IO。用户线程被阻塞在等待数据上或拷贝数据上。

非阻塞IO就是用户线程不参与以上两个过程,即数据已经拷贝到用户空间后,才去通知用户线程,一上来就可以直接操作数据了。

用户线程没有因为IO的事情出现阻塞,这就是常说的非阻塞IO。

同步IO和同步阻塞IO

按照上文中对同步的理解,同步IO是指发起IO请求后,必须拿到IO的数据才可以继续执行。
按照程序的表现形式又分为两种:
在等待数据的过程中,和拷贝数据的过程中,线程都在阻塞,这就是同步阻塞IO。
在等待数据的过程中,线程采用死循环式轮询,在拷贝数据的过程中,线程在阻塞,这其实还是同步阻塞IO。

网上很多文章把第二种归为同步非阻塞IO,这肯定是错误的,它一定是阻塞IO,因为拷贝数据的过程,线程是阻塞的。
严格来讲,在IO的概念上,同步和非阻塞是不可能搭配的,因为它们是一对相悖的概念。
同步IO意味着必须拿到IO的数据,才可以继续执行。因为后续操作依赖IO数据,所以它必须是阻塞的。
非阻塞IO意味着发起IO请求后,可以继续往下执行。说明后续执行不依赖于IO数据,所以它肯定不是同步的。
因此,在IO上,同步和非阻塞是互斥的,所以不存在同步非阻塞IO。但同步非阻塞是存在的,那不叫IO,叫操作数据了。

所以,同步IO一定是阻塞IO,同步IO也就是同步阻塞IO。

异步IO和异步阻塞/非阻塞IO

按照上文中对异步的理解,异步IO是指发起IO请求后,不用拿到IO的数据就可以继续执行。

用户线程的继续执行,和操作系统准备IO数据的过程是同时进行的,因此才叫做异步IO。
按照IO数据的两个过程,又可以分为两种:
在等待数据的过程中,用户线程继续执行,在拷贝数据的过程中,线程在阻塞,这就是异步阻塞IO。
在等待数据的过程中,和拷贝数据的过程中,用户线程都在继续执行,这就是异步非阻塞IO。

第一种情况是,用户线程没有参与数据等待的过程,所以它是异步的。但用户线程参与了数据拷贝的过程,所以它又是阻塞的。合起来就是异步阻塞IO。
第二种情况是,用户线程既没有参与等待过程也没有参与拷贝过程,所以它是异步的。当它接到通知时,数据已经准备好了,它没有因为IO数据而阻塞过,所以它又是非阻塞的。合起来就是异步非阻塞IO。

PS:聪明的你或许发现了我没有提多路复用IO,因为它值得专门撰文一篇。

(END)


  • 原作者姓名:李新杰
  • 原出处:微信公众号【编程新说】
  • 原文链接:https://mp.weixin.qq.com/s/0W9aHAGqyTfPkyOPF-Z_Xw

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/442483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

计算机毕设-文献摘要,毕设摘要翻译,要人工翻译,不要电脑网站翻译的。

满意答案雅固jiajia2013.09.06采纳率:44% 等级:12已帮助:5657人Blueberry somaclone as experimental material, studied the different cutting substrates, concentration of IBA on the somaclone outside the bottle to take root and…

mongodb不等于某个值_MongoDB的安装以及基本增删改查命令

MongoDB 介绍mongodb 和大多数NoSQL 数据库(redis,memcached 等)一样,都是以 kv数据库(key/value) 存储数据不同的是mongodb 文档数据库,存储的是文档(Bson->json的二进制化).特点:内部执行引擎为JS解释器, 把文档存储成bson结构,在查询时,转换为JS对象,并可以通…

Adobe网页无法访问服务器,Adobe Acrobat时提示“无法访问网络位置\startup”

于安装Adobe Acrobat时提示“无法访问网络位置\startup”问题的解决...先前一直没法安装Adobe Acrobat,是因为安装过程中出现了"无法访问网络位置\startup"的提示信息,点击“取消”后自动退出安装程序。最初一直以为是软件版本或者是系统兼容性…

python创建nc文件_如何python写nc文件

今天试了一下用PyNIO写nc文件,难用的一腿算了,还是用netcdf模块写了。代码如下:# -*- coding: utf-8 -*-import numpy as npimport sysimport osfrom netCDF4 import Datasetdef creatspinc(value, filename):gridspi Dataset(filename, w, …

显示器接服务器后黑屏,笔记本外接显示器黑屏怎么修复_笔记本外接显示器后黑屏的处理方法...

笔记本外接显示器能够将笔记本屏幕上的内容投影到更大的显示器上,使用起来更加舒服。不过有的小伙伴在操作时,却碰到了笔记本外接显示器黑屏的问题,对此我们该怎么来修复呢?下面系统城小编就来为大家分享关于笔记本外接显示器后黑…

绿联怎么样_移动电源降价了,小米、京选、绿联充电宝怎么选,网友:都非常合适...

我是一个手机“电量恐惧症”患者,如果出门,只要手机电量不足60%就感到恐惧担心,如果在不可预知时间的外出时,移动电源成了我出门必备。市面上5000、10000、20000mAh产品琳琅满目,经过挑选,我锁定了10000mAh…

wlandns服务器未响应,新东方在线APP客户端常见问题及解决办法

苹果设备常见问题:1、苹果设备下载APP后,调整了音量,但仍无声音?静音状态下,课件播放就会无声音,同学可调整一下手机的侧拨键,一般可恢复正常。2、苹果设备全屏播放时不能180度旋转?…

react方法返回html_React全家桶之React基础(推荐新手必看)

学习目标安装create-react-app脚手架熟练React基础语法掌握JSX语法掌握setState掌握React生命周期掌握props传递参数掌握React组件通信资源reactcreate-react-app 起步上手npm i -g create-react-app 安装官方脚手架create-react-app 01_react 初始化react的api比较少,基本学习…

华为4g无线路由器虚拟服务器设置方法,华为4g2pro路由器虚拟服务器设置

华为4g2pro路由器虚拟服务器设置 内容精选换一换当前在部分区域中,路由表已从虚拟私有云中解耦,解耦后路由表拥有独立入口,支持路由表与子网关联功能,请以实际界面为准。未解耦:在虚拟私有云详情页的“路由表”页签&am…

echarts加载动画效果_入门ae教程:科技类的加载动画,非常酷炫的效果,附带教程...

效果图今天这个教程属于初学者的教程,很简单,但是科技类的加载动画,我个人觉得都是非常酷的(每天5分钟,充实一整天)教程1、首先打开我们的AE2、新建一个合成,1080*660px,持续时间10秒将我们的素材导入AE中&…

dell服务器T100无法进入系统,DELL服务器开机Alert!Cover was previously removed F1

服务器是戴尔的,dell poweredge T100。开机之后出现Alert!Cover was previously removed.Strke F1 to retuy boot. F2 for setup utility.它的意思是“主机盖被移动了”。是机箱防盗监测机箱防盗监测器可以检测到机箱是否被打开。系统设置程序中的“Chas…

结果显示窗口如何缩小_Proe草绘时提示“截面再生失败。不合适的尺寸”如何处理?...

我们在Proe中草绘的时候一般都是先绘制出整个草绘的大致外形,然后再标注尺寸,由于起初没有把握好尺寸的大小,外形虽然大致相同,但是当前的草绘尺寸与目标草绘尺寸大小差别过大就会出现这样的一个情况:系统会在信息栏提…

python判断语句入门教程_Python中的条件判断语句基础学习教程

if语句用来检验一个条件, 如果 条件为真,我们运行一块语句(称为 if-块 ), 否则 我们处理另外一块语句(称为 else-块 )。 else 从句是可选的。使用if语句:?输出:?在这个程序中,我们从用户处得到猜测的数&a…

把变量赋值给寄存器_散装 vs 批发谁效率高?变量访问被ARM架构安排的明明白白...

作为过来人,我发现很多程序猿新手,在编写代码的时候,特别喜欢定义很多独立的全局变量,而不是把这些变量封装到一个结构体中,主要原因是图方便,但是要知道,这其实是一个不好的习惯,而…

威海二职工业机器人专业_工业机器人专业就业前景-山东省好的中专学校

济南电子机械工程学校,高考升学班,圆您大学梦!职教高考说明:山东省自2012年起,普通高校考试招生分春季高考与夏李高考。2020年春季高考开级为职教高考,重点面向中等职业学校学生,考试科目由知技能两部分组成。“知识”…

ls mac 显示最近修改日期_如何在Mac上按日期排序文件 | MOS86

许多Mac用户按名称和类型对文件进行排序,但是按日期排序档案最有用的方法之一就是。Mac Finder可以为文件,文档,应用程序和文件夹提供各种不同的基于日期的排序选项,并且它们通常在Finder列表视图中最为有效。在Mac OS中使用基于日…

python 正则表达式 断言 不定长表达式_MyEssay 之 Python正则表达式 —— 四种断言扩展的理解...

我们经常用正则表达式来检测一个字符串中包含某个子串,要表示一个字符串中不包含单个的某字符或某些字符也很容易,用[^...]形式就可以了。但是要表示一个字符串中不包含某个子串(由字符序列构成)的时候,用[^...]这种形式就不行了,…

python爬虫请求头是什么意思_python爬虫请求头的使用

这篇文章我们来讲一下在网站建设中,python爬虫请求头的使用。本文对大家进行网站开发设计工作或者学习都有一定帮助,下面让我们进入正文。爬虫请求头网页获取:通过urlopen来进行获取requset.urlopen(url,data,timeout)第一个参数url即为URL&a…

复化科特斯公式matlab_matlab实现复化NewtonCotes公式求积分的程序应用和代码

命令窗口输入被积函数2120ttedt。输入应为:。Step2:执行函数。输入形式为mymulNewtonCotes(ft,a,b,m,n);其中ft—被积函数,此体重,已经在第一步赋值;a—积分下限,本题中为0;b—积分…

单元格自适应宽度_最详细的Excel模块Openpyxl教程(二)-单元格操作详解

在以前的推文中,我们介绍了操作Excel的模块openpyxl的入门知识,相关推文可以从本公众号的底部相关菜单获取。接下来的推文我们来学习一下openpyxl这个python模块中的其他知识,本次推文我们来学习一下单元格(cell)操作的…