写点什么

【死磕 NIO】— 阻塞、非阻塞、同步、异步,傻傻分不清楚

用户头像
chenssy
关注
发布于: 1 小时前
【死磕NIO】— 阻塞、非阻塞、同步、异步,傻傻分不清楚

万事从最基本的开始。


要想完全掌握 NIO,并不是掌握上面文章(【死磕NIO】— NIO基础详解)中的三大组件就可以了,我们还需要掌握一些基本概念,如什么是 IO,5 种 IO 模型的区别,什么是阻塞 &非阻塞等等,只有掌握了这些基本概念,我们对 NIO 才能理解得更加得心应手。


这篇文章我们就从阻塞 &非阻塞,同步 &异步说起。

同步与异步

什么是同步与异步呢?百度百科是这样定义的:


同步指两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。


异步与同步相对(这解释让我无言相对)


所以,我们需要明确的是**同步与异步针对的是两个或者两个以上的事物**。


对于同步而言,一个任务(调用者)的完成需要依赖另一个人任务(被调用者)的完成,只有等待被依赖的任务完成,依赖的任务才会继续进行,两者步调保持一致。


异步呢?任务与它依赖的任务没有必然的联系,它不需要等待它依赖的任务完成,它只需要向依赖任务发起调用即可,告诉它你可以干活了,至于你啥时候干完跟我没关系。


所以说,同步和异步的本质区别就在于调用者与被调用者之间结果消息通知机制的不同


  • 同步:调用者需要一直主动等待被调用者的结果。

  • 异步:调用者调用被调用者后,调用者不会立刻得到结果,在调用者发起调用后,被调用者通过状态、通知或通过回调函数,让调用者知道结果


所以,同步和异步一个是主动等待结果,一个是被动知道结果。


举一个简单的例子:买奶茶,我们有两种方式拿到我们买的奶茶


  • 选择排队等待。这种方式就是同步等待消息通知了,我们需要一直在吧台面前等着我们的奶茶

  • 扫码。这种方式,你可以不停地看手机排号是否到你了(状态),也可以在那里玩手机等着服务员喊 88 号,奶茶好了(通知)。


上面提到异步调用可以通过状态、通知或者回调函数来告知调用者。


  • 状态:调用者需要每隔一段向被调用者发起一个状态查询请求。这种方式效率较为低下。一般我们在调用支付接口的时候,如果服务方告知支付状态未知,则我们需要每隔一段时间去查询该笔订单的支付状态。虽然效率较为低下,但是靠谱。

  • 通知:这种方式,调用者不需要做额外的工作,他只需要等被调用者把结果告诉调用者即可。但是这种方式也有点不是那么靠谱,它到底啥时候调用,如果不调用怎么办呢?这些都是我们需要考虑的问题。

  • 回调函数:和通知机制差不多。

阻塞与非阻塞

上面解释了什么是同步与异步,那什么是阻塞与非阻塞呢?


所谓阻塞,就是有障碍而不能通行,无法畅通。


所以,阻塞就是调用结果返回之前,该线程会被一直挂起,一直等待结果,不能继续,函数只有在得到结果之后才会返回


可能有小伙伴会将阻塞与同步等同起来,因为他们都是因为等待执行结果而停滞不前,其实两者还是有区别的:


  • 同步,针对的是两个进程,一个进程(调用者)因为等待另一个进程(被调用者)的执行结果而停滞不前。而阻塞则是针对一个,它是因为自己本身因等待当前线程中某个执行结果而停滞不前的。

  • 对于同步来说,当前线程还是处于激活状态,只是从逻辑(感官)来说它是停滞不前的,当前线程可能还在处理其他事情。而阻塞则不同,当前线程是被挂起了,直接让出了 CPU。


非阻塞则与阻塞概念相对,指在不能立即得到执行结果之前,该函数不会阻碍当前线程执行,而是会立即返回


还是上面那个买奶茶的例子,不论是排队在那里等奶茶还是扫码在哪里等奶茶,只要在等奶茶的过程中你没有做其他事情都是阻塞。如果你在等的过程跟你女朋友聊天(假如你有女朋友的话)或者在玩手机,那么就是非阻塞,因为没有因等待奶茶这件事一直耗着,而是一边等一边干其他的事情。

同步 &异步、阻塞 &非阻塞

同步 &异步与阻塞 &非阻塞两两组合,分别为同步阻塞,同步非阻塞异步阻塞异步非阻塞。以上面等奶茶的例子为例。


同步阻塞


你在排队等奶茶的过程中,什么事情都不能做,只能干等着。就问你无聊不无聊,尴尬不尴尬。效率最为低下


同步非阻塞


你在排队等奶茶的过程中,可以干其他事情,比如刷抖音,玩一把王者荣耀,但是你需要不断地看奶茶是否已经到你,你势必会分心导致输掉王者荣耀,成为一个坑货。注意排队等奶茶,玩王者荣耀是两件事情,你需要两件事情来回不断地切换,效率也不见得高到哪里去


异步阻塞


你扫码拿号后,你不用在那里排队干等,你只需要等候服务员告诉你奶茶做好了去拿就可以了,但是在这个等的过程中,你啥事都不能干,只能干等着。很显然你已经被阻塞在这个等待服务员告诉你奶茶做好了的事情(消息通知)上面了。我们要注意是,并不是说异步就不能阻塞了,异步也是可以阻塞的,只不过它不是在处理消息时阻塞,而是在等待消息通知时被阻塞了


异步非阻塞


你扫码拿号后,直接去边上玩王者荣耀了,中途你专心玩的王者荣耀,不需要分心去关注你的奶茶是否做好了,你只需要在那里等服务员告诉你奶茶做好了(消息通知)去拿就可以了。效率最高

参考资料

发布于: 1 小时前阅读数: 5
用户头像

chenssy

关注

『Java 技术驿站』、死磕 Java 系列 2018.03.24 加入

全职 Java 程序员,兼职写文章,专注【死磕 Java】系列文章创作,一个立志做专业的程序员...

评论

发布
暂无评论
【死磕NIO】— 阻塞、非阻塞、同步、异步,傻傻分不清楚