【死磕NIO】— 阻塞、非阻塞、同步、异步,傻傻分不清楚
万事从最基本的开始。
要想完全掌握 NIO,并不是掌握上面文章(【死磕NIO】— NIO基础详解)中的三大组件就可以了,我们还需要掌握一些基本概念,如什么是 IO,5 种IO模型的区别,什么是阻塞&非阻塞等等,只有掌握了这些基本概念,我们对NIO才能理解得更加得心应手。
这篇文章我们就从阻塞&非阻塞,同步&异步说起。
同步与异步
什么是同步与异步呢?百度百科是这样定义的:
同步指两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。
异步与同步相对(这解释让我无言相对)
所以,我们需要明确的是同步与异步针对的是两个或者两个以上的事物。
对于同步而言,一个任务(调用者)的完成需要依赖另一个人任务(被调用者)的完成,只有等待被依赖的任务完成,依赖的任务才会继续进行,两者步调保持一致。
异步呢?任务与它依赖的任务没有必然的联系,它不需要等待它依赖的任务完成,它只需要向依赖任务发起调用即可,告诉它你可以干活了,至于你啥时候干完跟我没关系。
所以说,同步和异步的本质区别就在于调用者与被调用者之间结果消息通知机制的不同。
- 同步:调用者需要一直
主动等待被调用者的结果。 - 异步:调用者调用被调用者后,调用者不会立刻得到结果,在调用者发起调用后,被调用者通过状态、通知或通过回调函数,让调用者知道结果
所以,同步和异步一个是主动等待结果,一个是被动知道结果。
举一个简单的例子:买奶茶,我们有两种方式拿到我们买的奶茶
- 选择排队等待。这种方式就是同步等待消息通知了,我们需要一直在吧台面前等着我们的奶茶
- 扫码。这种方式,你可以不停地看手机排号是否到你了(状态),也可以在那里玩手机等着服务员喊 88 号,奶茶好了(通知)。
上面提到异步调用可以通过状态、通知或者回调函数来告知调用者。
- 状态:调用者需要每隔一段向被调用者发起一个状态查询请求。这种方式效率较为低下。一般我们在调用支付接口的时候,如果服务方告知支付状态未知,则我们需要每隔一段时间去查询该笔订单的支付状态。虽然效率较为低下,但是靠谱。
- 通知:这种方式,调用者不需要做额外的工作,他只需要等被调用者把结果告诉调用者即可。但是这种方式也有点不是那么靠谱,它到底啥时候调用,如果不调用怎么办呢?这些都是我们需要考虑的问题。
- 回调函数:和通知机制差不多。
阻塞与非阻塞
上面解释了什么是同步与异步,那什么是阻塞与非阻塞呢?
所谓阻塞,就是有障碍而不能通行,无法畅通。
所以,阻塞就是调用结果返回之前,该线程会被一直挂起,一直等待结果,不能继续,函数只有在得到结果之后才会返回。
可能有小伙伴会将阻塞与同步等同起来,因为他们都是因为等待执行结果而停滞不前,其实两者还是有区别的:
- 同步,针对的是两个进程,一个进程(调用者)因为等待另一个进程(被调用者)的执行结果而停滞不前。而阻塞则是针对一个,它是因为自己本身因等待当前线程中某个执行结果而停滞不前的。
- 对于同步来说,当前线程还是处于激活状态,只是从逻辑(感官)来说它是停滞不前的,当前线程可能还在处理其他事情。而阻塞则不同,当前线程是被挂起了,直接让出了 CPU。
非阻塞则与阻塞概念相对,指在不能立即得到执行结果之前,该函数不会阻碍当前线程执行,而是会立即返回。
还是上面那个买奶茶的例子,不论是排队在那里等奶茶还是扫码在哪里等奶茶,只要在等奶茶的过程中你没有做其他事情都是阻塞。如果你在等的过程跟你女朋友聊天(假如你有女朋友的话)或者在玩手机,那么就是非阻塞,因为没有因等待奶茶这件事一直耗着,而是一边等一边干其他的事情。
同步&异步、阻塞&非阻塞
同步&异步与阻塞&非阻塞两两组合,分别为同步阻塞,同步非阻塞,异步阻塞,异步非阻塞。以上面等奶茶的例子为例。
同步阻塞
你在排队等奶茶的过程中,什么事情都不能做,只能干等着。就问你无聊不无聊,尴尬不尴尬。效率最为低下。
同步非阻塞
你在排队等奶茶的过程中,可以干其他事情,比如刷抖音,玩一把王者荣耀,但是你需要不断地看奶茶是否已经到你,你势必会分心导致输掉王者荣耀,成为一个坑货。注意排队等奶茶,玩王者荣耀是两件事情,你需要两件事情来回不断地切换,效率也不见得高到哪里去。
异步阻塞
你扫码拿号后,你不用在那里排队干等,你只需要等候服务员告诉你奶茶做好了去拿就可以了,但是在这个等的过程中,你啥事都不能干,只能干等着。很显然你已经被阻塞在这个等待服务员告诉你奶茶做好了的事情(消息通知)上面了。我们要注意是,并不是说异步就不能阻塞了,异步也是可以阻塞的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞了。
异步非阻塞
你扫码拿号后,直接去边上玩王者荣耀了,中途你专心玩的王者荣耀,不需要分心去关注你的奶茶是否做好了,你只需要在那里等服务员告诉你奶茶做好了(消息通知)去拿就可以了。效率最高。
参考资料
【死磕NIO】— 阻塞、非阻塞、同步、异步,傻傻分不清楚的更多相关文章
- 【死磕NIO】— 阻塞IO,非阻塞IO,IO复用,信号驱动IO,异步IO,这你真的分的清楚吗?
通过上篇文章([死磕NIO]- 阻塞.非阻塞.同步.异步,傻傻分不清楚),我想你应该能够区分了什么是阻塞.非阻塞.异步.非异步了,这篇文章我们来彻底弄清楚什么是阻塞IO,非阻塞IO,IO复用,信号驱动 ...
- 【转载】高性能IO设计 & Java NIO & 同步/异步 阻塞/非阻塞 Reactor/Proactor
开始准备看Java NIO的,这篇文章:http://xly1981.iteye.com/blog/1735862 里面提到了这篇文章 http://xmuzyq.iteye.com/blog/783 ...
- JAVA 中BIO,NIO,AIO的理解以及 同步 异步 阻塞 非阻塞
在高性能的IO体系设计中,有几个名词概念常常会使我们感到迷惑不解.具体如下: 序号 问题 1 什么是同步? 2 什么是异步? 3 什么是阻塞? 4 什么是非阻塞? 5 什么是同步阻塞? 6 什么是同步 ...
- 【面试】迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章(快快珍藏)
常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HTTP接口拿到详情数据,然后使用适合的视图展示详情数据. 如果网速很慢,代码发起一个HTTP请求后,就卡住不动了,直到十几秒后才拿到HTT ...
- 【转载】迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章(快快珍藏)
原文链接:https://www.cnblogs.com/lixinjie/p/10811219.html 常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HTTP接口拿到详情数据,然后使 ...
- 同步/异步/阻塞/非阻塞/BIO/NIO/AIO
转摘自:https://www.cnblogs.com/lixinjie/p/a-post-about-io-clearly.html 常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HT ...
- 迄今为止把同步/异步/阻塞/非阻塞/BIO/NIO/AIO讲的这么清楚的好文章(快快珍藏)
常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HTTP接口拿到详情数据,然后使用适合的视图展示详情数据. 如果网速很慢,代码发起一个HTTP请求后,就卡住不动了,直到十几秒后才拿到HTT ...
- 同步/异步/阻塞/非阻塞/BIO/NIO/AIO各种情况介绍
常规的误区 假设有一个展示用户详情的需求,分两步,先调用一个HTTP接口拿到详情数据,然后使用适合的视图展示详情数据. 如果网速很慢,代码发起一个HTTP请求后,就卡住不动了,直到十几秒后才拿到HTT ...
- 进程&线程 同步异步&阻塞非阻塞
2015-08-19 15:23:38 周三 线程 线程安全 如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码 线程安全问题都是由全局变量及静态变量引起的 若每个线程中对 ...
随机推荐
- 【笔记】jupyter notebook基础使用
jupyter notebook基础使用 执行代码 添加格子 在输出结果的同时添加一行 run cells and insert below 输出结果,若后续没有新的代码行了,则会在后面添加一行 查看 ...
- 【笔记】逻辑回归中使用多项式(sklearn)
在逻辑回归中使用多项式特征以及在sklearn中使用逻辑回归并添加多项式 在逻辑回归中使用多项式特征 在上面提到的直线划分中,很明显有个问题,当样本并没有很好地遵循直线划分(非线性分布)的时候,其预测 ...
- Swagger在线文档使用教程
springboot整合Swagger2 1.首先创建一个springboot工程,在pom文件内导入依赖 <!--swagger依赖--> <!--Swagger2- ...
- 使用 C# 下载文件的十八般武艺
文件下载是一个软件开发中的常见需求.本文从最简单的下载方式开始步步递进,讲述了文件下载过程中的常见问题并给出了解决方案.并展示了如何使用多线程提升 HTTP 的下载速度以及调用 aria2 实现非 H ...
- 一文搞懂Java/Spring/Dubbo框架中的SPI机制
几天前和一位前辈聊起了Spring技术,大佬突然说了SPI,作为一个熟练使用Spring的民工,心中一紧,咱也不敢说不懂,而是在聊完之后赶紧打开了浏览器,开始的学习之路,所以也就有了这篇文章.废话不多 ...
- redis的过期策略和淘汰策略
过期键删除策略 1.定时删除:在设置键的过期时间的同时,创建一个定时器timer,让定时器在键过期时间来临时,立即执行对键的删除操作. 2.惰性删除:放任键过期不管,但是每次从键空间中获取键时,都检查 ...
- Python爬虫(二)——发送请求
1. requests库介绍 在python中有许多支持发送的库.比如:urlib.requests.selenium.aiohttp--等.但我们当前最常用的还是requests库,这个库是基于 ...
- 连接共享打印机失败错误代码0x80070035
局域网内共享打印机非常方便,但是在连接中经常遇到问题,其中出现错误代码0x80070035的概率非常之高! 1.必须确保有关打印功能的相关服务都处于自动启动状态,重点检查TCP/IP NetBIOS ...
- Java知识图谱(附:阿里Java学习计划)
摘要: 本文主要描绘了Java基础学习过程,给出Java知识结构图,以及阿里Java岗学习计划,对Java学习爱好者.准备及将要从事Java开发方面的同学大有裨益. 温馨提示: 由于C ...
- jQuery中的基本选择器(四、一):* 、 . 、element(直接标签名)、 或者用逗号隔开跟多个
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...