什么是阻塞、非阻塞、同步和异步以及IO模型
首先先看如下几个问题,或者说我们经常会遇到的问题。
阻塞是否等于同步?
非阻塞是否等于异步?
同步一定是阻塞的么?
异步一定是非阻塞的么?
要把这四个概念讲明白,先从一顿简餐说起。假设你要做一顿便饭:烧土豆;烧茄子和米饭。CPU代表你,如下事件代表操作:
A1、切土豆、A2、烧土豆
B1、切茄子、B2、烧茄子
C1、淘米、C2、煮饭;
情况1:你做完A1再做B1再做C1,即:切完土豆、切茄子最后淘米;
情况2:你干一会A1再干一会B1,再干一会C1,即:一会切土豆、一会切茄子、一会淘米,直到三者做完;
情况1相当于开一个线程按顺序做,情况2相当于开三个线程分别作A1、B1、C1;
对于你来说:情况1显然要比情况2好,因为减少了切换时间,也就是说减少了不必要的拿起土豆,放下土豆,拿起茄子放下茄子的时间,这个时间就是CPU线程切换时所带来的额外开销,想象一下你要做100个菜。你的时间将大量耗在拿起某个菜放下某个菜的过程中,而不是干正事切菜配菜上。
A1、B1、C1对你来说是纯体力活,要全程参与,相当于CPU的纯运算操作。此时开多个线程分别做,还不如开一个线程一个一个按顺序做。
情况真是如此么?
如果你能像周伯通那样双手互搏,左手削土豆,右手削茄子,那么你就是双核CPU。如果你还能把双脚利用起来,左脚切冬瓜,右脚淘米,那么你就是四核CPU。你的工作效率将会大幅提升,还能给自己加一个菜:烧冬瓜。
那么真的会有提升么?
假设你已打通任督二脉,练到了4核的境地,你也愉快的开启了4个线程,不幸的是4个线程都开在了左手上,那你的左手效率将大幅提升:削土豆、削茄子、切冬瓜和淘米,不停的在左手切换。但右手和双脚会闲的蛋疼。虽然你是个4核,但低调的像个单核,甚至还不如单核。因此你要尽可能的将这4个线程分配到不同的手脚上去干不同的事。
上述三个操作完成只是做一顿饭的前戏,你还要把他们烧熟。
此时你还要完成 A2(烧土豆)、B2(烧茄子)、C2煮饭。 相对于A1B1C1,这三个操作你不需要全程参与,大部分时间是交给煤气灶、电饭煲完成。你只需要把土豆扔锅里,加点水和调料等待煮熟即可(这里将就一下,不讲究口味,要啥自行车)。A2、B2、C2相当于IO操作,你参与的时间很少,大部分是等待结果。
情况3:你做完A2再做B2再做C2,即:烧完土豆、烧茄子、最后煮饭,此时你就在厨房啥事不干就是干等;
情况4:你做A2的同时,又开了一个煤气灶烧了茄子,同时又将米放入电饭煲中开煮,然后你去客厅看乡爱N部曲。
对你而言显然情况4要优于情况3,做一顿饭的时间将大幅缩短,你不用一直呆在厨房,你还有时间去看电视。情况3就是阻塞同步。
你真的能安心看好电视么?
显然不能,你要确保土豆、茄子是否烧熟或者是否烧糊,就要不停从客厅到厨房去查看一下,这就是非阻塞轮询。虽然比情况3好一点,但也好不到哪去,因为你要往返跑,还能让人愉快的看东北F4么?在你忙着从厨房到客厅,客厅到厨房的时候,电饭煲发出了“biu”的一声,此时你知道饭烧好了。
A2、B2的操作对你而言就是非阻塞轮询,虽然不阻塞了(在厨房傻等)可惜累成狗。C2操作对你而言就是异步,电饭煲把饭做好后通知你结果,这样你就无需像烧土豆、茄子那样跑断腿。
此时你的女朋友来了!!
你很激动,需要临时加几个菜。这时候你可以在等A2、B2、C2结果的同时,处理其它菜品,比如切西红柿、清洗小龙虾、做个狮子头、拌个凉菜,甚至出去买瓶酒。土豆烧好后,你就烧西红柿;米饭煮好后你就烧龙虾,烧龙虾时你又可以剁肉做狮子头。这样你可以一直烧下去,烧很多很多菜。
这时候你的利用率是最高的,几乎没有等待时间,因为你的女朋友来了你很开心,开心的想一直烧下去。。。。。。
这时候你必然会发挥自己的多核性能,把你四肢的主观能动性都调动起来,而且会调度的很均衡,让电视里的尼古拉斯赵四见鬼去吧。。。。。。
这时候你会发现自己已经从一个纯粹的CPU进化为一个懂业务的高性能服务器:高并发、高吞吐量和低延迟。你的女朋友对你的性能相当满意,并对你的这一系列骚操作起了一个名字:非阻塞异步!
因为有了IO操作才会有阻塞,才会出现同步和异步。因为有大量IO操作,才会有高并发的设计,如果只是纯CPU运算,不涉及到CPU对外围IO设备的读写,那么就不存在高并发设计。也就是说无论切土豆还是切茄子,都是纯体力工作,纯CPU运算工作。那么对CPU而言,开一个线程计算和开100个线程计算,只会徒增CPU切换时间,当然这种情况下也不存在所谓的阻塞、非阻塞、同步和异步。所谓的高性能就是如何在处理大量IO的情况下,让CPU去干更多的正事(切菜配菜烧菜),而不是去等待或者去看电视。
虽然你的女朋友对你很满意,但你并不能骄傲,你还有提升的空间,就是如何提升自己洗菜、配菜的速度,就业务而言就是如何设计高效的内存池、缓存、Hash表。。。。,这样你就可以在等待IO结果的同时,处理更多的业务了。
回到本文开头的四个问题
就CPU而言IO阻塞是绝对的,因为所有设备都不会快过CPU。只是有的设备快有的慢,有的稳定有的不稳定,比如磁盘IO相对于网络IO就比较快速和稳定。阻塞和非阻塞的意义在于内核在这种绝对阻塞上呈现给应用层的形式。换句话说,就是内核给应用层提供访问这些IO的函数是阻塞的还是非阻塞的,这两者的差别就导致了后面的同步和异步。
——————————————最后收尾总结一下————————————————
阻塞和非阻塞是指内核提供给应用层的IO访问函数是等待IO结果返回还是立即返回,等待结果的就是阻塞函数,立即返回的就是非阻塞函数,是针对函数而言;
同步和异步是指应用层在调用内核的阻塞函数或非阻塞函数后所才取的处理方式,是针对操作而言。
如果内核只提供阻塞IO函数,你的应用层操作必然是同步;
如果内核也提供了非阻塞IO函数,你的应用层操作可能是同步,也可能是异步;
如果内核没有提供IO完成通知机制,你的应用层也无法实现完全的异步。
这些函数和操作的组合就产生了不同的IO模型,或者说阻塞函数、非阻塞函数、同步操作、异步操作之间的组合就是IO模型。通常有四种组合:同步阻塞,同步非阻塞,异步阻塞,异步非阻塞。
编写服务器时,我们大部分使用的是异步阻塞IO模型。就是既调用了阻塞函数,也调用了非阻塞函数。比如读写操作是非阻塞的,但select/wait却是阻塞的。这种模型在windows下衍生出了事件(Event)和重叠(Overlapped)模型。在linux下衍生出了poll和epoll模型。不同的IO模型适用于不同业务场景,需要根据你的具体业务而定。如果只是客户端程序,阻塞同步就很好,代码简洁清晰。
什么是阻塞、非阻塞、同步和异步以及IO模型的更多相关文章
- 异步|同步&阻塞|非阻塞
异步|同步:区别在于发出一个功能调用时,是否马上得到返回结果 阻塞|非阻塞:区别在于调用结果返回之前,当前线程是否挂起 node.js:单线程.异步非阻塞模型 单线程与异步不矛盾,与并发是矛盾的 ht ...
- 阻塞非阻塞,同步异步四种I/O方式
举一个去书店买书的例子吧: (同步)阻塞: 你去书店买书,到柜台告诉店员,需要买一本APUE,然后一直在柜台等.(阻塞) 店员拿到书以后交给你. (同步)非阻塞: 你去书店买书,到柜台告诉店员A,需要 ...
- 进程&线程 同步异步&阻塞非阻塞
2015-08-19 15:23:38 周三 线程 线程安全 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码 线程安全问题都是由全局变量及静态变量引起的 若每个线程中对 ...
- I/O阻塞非阻塞,同步异步
http://www.cnblogs.com/luotianshuai/p/5098408.html "阻塞"与"非阻塞"与"同步"与&qu ...
- 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor
开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...
- 高性能IO设计模式之阻塞/非阻塞,同步/异步解析
提到高性能,我想大家都喜欢这个,今天我们就主要来弄明白在高性能的I/O设计中的几个关键概念,做任何事最重要的第一步就是要把概念弄的清晰无误不是么?在这里就是:阻塞,非阻塞,同步,异步. OK, 现在来 ...
- Python番外之 阻塞非阻塞,同步与异步,i/o模型
1. 概念理解 在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非阻塞(Unblock)四种调用方式: 同步/异步主要针对C端: 同步: 所谓同步,就 ...
- 阻塞与非阻塞、同步与异步 I/O模型
I/O模型 Linux 下的五种I/O模型 阻塞I/O(blocking I/O) 非阻塞I/O (nonblocking I/O) I/O复用(select 和poll) (I/O multiple ...
- JAVA 中BIO,NIO,AIO的理解以及 同步 异步 阻塞 非阻塞
在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步 ...
随机推荐
- Win64 驱动内核编程-32.枚举与删除注册表回调
枚举与删除注册表回调 注册表回调是一个监控注册表读写的回调,它的效果非常明显,一个回调能实现在SSDT 上 HOOK 十几个 API 的效果.部分游戏保护还会在注册表回调上做功夫,监控 service ...
- (邹博ML)矩阵和线性代数
主要内容 矩阵 特征值和特征向量 矩阵求导 矩阵 SVD的提法 奇异值分解(Singular Value Decomposition)是一种重要的矩阵分解方法,可以看做对称方阵在任意矩阵上的推广. 假 ...
- java-处理大容量文本文件,行内分格符为TAB的方法
以处理某sql文件为例 源文件中行格式为: 123456 7895433 xxxxx yyyyy zzzzz 行间分隔符为 TAB. 转换完后文件中行的格式为: 123456,7895433,xxx ...
- Java 进行时间处理
Java 进行时间处理 一.Calendar (1).Calender介绍 Calendar的中文翻译是日历,实际上,在历史上有着许多种计时的方法.所以为了计时的统一,必需指定一个日历的选择.那现在最 ...
- Mybatis学习之自定义持久层框架(七) 自定义持久层框架优化
前言 接上文,这里只是出于强迫症,凭借着半年前的笔记来把之前没写完的文章写完,这里是最后一篇了. 前面自定义的持久层框架存在的问题 Dao层若使用实现类,会存在代码重复,整个操作的过程模版重复(加载配 ...
- VS2017报错 由#define后的分号引发的【“ 应输入“)】
其实并不是第十行分号出现了问题,而是由于在宏定义后面加了分号,修改成这样即可 一开始竟然没看出来--甚至以为是VS中出现"宏可以转换为constexpr"问题--下次要仔细--
- python爬虫——《瓜子网》的广州二手车市场信息
由于多线程爬取数据比单线程的效率要高,尤其对于爬取数据量大的情况,效果更好,所以这次采用多线程进行爬取.具体代码和流程如下: import math import re from concurrent ...
- apiAutoTest:基于mitmproxy实现接口录制
目录 apiAutoTest 目前功能 重大更新(个人认为) 本次更新 契机 根本 如何录制 录制的用例 执行录制的用例 执行结果 实现源码 参考资料 apiAutoTest 先软文介绍下:apiAu ...
- [Python] Python工匠(Github)
1.善用变量来改变代码质量 变量命名 变量要有描述性,不能太宽泛 BAD:day, host, cards, temp GOOD:day_of_week, hosts_to_reboot, expir ...
- ltp日志
grep "fail" -i /var/log/messages |wc -lgrep "fail" -i /var/log/messagesgrep &quo ...