深入理解同步和异步阻塞和非阻塞并行和串行这几个概念
Posted 明明如月学长
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深入理解同步和异步阻塞和非阻塞并行和串行这几个概念相关的知识,希望对你有一定的参考价值。
一、背景
晚上技术群里有朋友问,“同步和阻塞色区别是什么?”
有不少朋友给出去了自己的看法,部分内容如下:
其中有朋友给出了截图,图上给出了比较“生动”的例子。
然而,看完之后似乎懂了,似乎又没懂。
很多人对这几个常见的概念,似乎熟悉而又陌生。
二、理解
2.1 前缘
如果之前有同学看过我的 《我眼中的Java大牛之孤尽老师》 这篇文章,就会发现里面已经提及一二,遗憾的是大多数同学都是遇到问题的时候才想着去问去看。
2.2 视角
对于这个问题,我更倾向于大家以视角的思维去看。
同步和异步是函数调用视角
即同步执行函数调用后,必须等待函数返回才能继续执行;异步则不需要等待返回即可继续执行其他任务。
比如领导安排你去打印一本几百页的电子书,同步的话相当于你自己亲自去打印,打印时一直在打印机器边上等待打印完成,再去干其他事情;异步的话我们点击完打印之后就去干其他事情,如点击打印之后先去刷个剧或者我们请另外一个同学帮我们打印,然后自己去干其他事情。
回到具体业务上来,假设我们需要在系统登录成功之后给用户发短信通知,我们在登录完毕之后,使用线程池起线程或者发送消息队列消息通知下游去执行短信发送,登录方法不必等发送短信程序执行完毕就可以直接返回。
阻塞和非阻塞是线程视角
在我看来,阻塞和非阻塞是描述线程状态。
所谓阻塞是指执行某个调用后当前线程被挂起(如生产消费者模型中,无消费内容时 wait),释放CPU ,直到等得到结果被唤醒(有可消费内容时 通过 notifyAll 唤醒消费线程);非阻塞是指执行某个调用后,即使不能立刻得到结果,当前线程也不会被挂起。
比如出租车司机,接到乘客之后,前面的牌子就要翻到 [有人],此时无法继续接客,知道乘客下车结束订单,这就是[阻塞];出租车司机接到乘客后不将牌子翻到[有人],即使当前一个乘客没有送到目的地,还可以继续接单,则就是[非阻塞]。
通常[阻塞]会造成线程进入挂起状态(效果如调用了 wait 方法),[同步]调用时线程还是运行状态,正在执行函数调用(效果如调用了 sleep 方法),只不过调用还没有返回。
并行和串行是 CPU 视角
并行任务通常可以拆分成多个步骤,多个CPU 核心一起执行,这类任务之间通常没有依赖关系,完全正交;串行任务每一个步骤同时只能有一个核心执行,通常有上下游依赖关系。
我们可以将多个人比喻为多个CPU核心。比如我们想把大象装冰箱里,就要先打开 冰箱门,然后把大象装进去,然后再关上冰箱门,即使我们有多个人,但是步骤不能同时执行。即不能冰箱门还没打开就直接装大象,也不能大象还没进去就直接关闭冰箱门,这就是[串行]。
我们如果想出版一本书,可以将书拆分成不同的章节,然后每人分一个章节,大家一起写,此时在时间上多人是在一起做任务,而且对进度都有帮助,这就是[并行]。
沿用这个例子,我们想下[并行] 和 [并发] 的区别,并发相当有我们只有一个人,可以一会写第一章,一会写第二章,一会写第三章,然后再写第一章等,虽然可以切换做不同的事情,但是只有一个人。
三、总结
对于这几个概念,希望大家能够抓住本质,而不要被各种例子所迷惑。
同步和异步是函数调用视角,判断依据是调用之后是否需要等待返回。
阻塞和非阻塞是线程视角,即调用之后当前线程是否被挂起。
并行和串行是 CPU 视角,即是否同时有多核一起承担同一项任务。
本文只是谈谈自己的理解,如果有疏漏,大家可以评论和我交流,也欢迎大家给出更通俗易懂的理解方式。
创作不易,如果本文对你有帮助,欢迎点赞、收藏加关注,你的支持和鼓励,是我创作的最大动力。
以上是关于深入理解同步和异步阻塞和非阻塞并行和串行这几个概念的主要内容,如果未能解决你的问题,请参考以下文章