其他分享
首页 > 其他分享> > 通俗系列之同步、异步、阻塞和非阻塞

通俗系列之同步、异步、阻塞和非阻塞

作者:互联网

前言

在日常的开发中,经常出现同步、异步、阻塞和非阻塞等概念。有些人搞不清楚什么代码是同步,什么代码是异步。有些人说我用异步了啊,为什么效率还是没提高呢?也许你是用异步了,但是可能是异步阻塞了。有些人一听说异步好,就不管三七二十一,所有方法全部改成异步,然后就会产生新的问题。归根结底还是对同步、异步、阻塞和非阻塞的概念不理解。

那究竟什么是同步、异步、阻塞和非阻塞呢?我决定尝试用比较通俗的例子举例来解释一下,于是便有了这篇文章。

同步

概念

什么是同步?同步就是一个任务的完成依赖于另外一个任务,只有被依赖的任务完成后,那么依赖的任务才能继续完成。

这是一种非常可靠的任务序列,要么都成功,要么都失败。

就和以前的瀑布式开发一样,你要做一个项目,一定要严格按照需求、分析、设计、编码、测试的步骤顺序执行,如果其中有一个问题卡住了,那么后边就无法继续,如果其中有一个环节是搞错了,那么这个项目也就可能死掉了。

同步又分同步阻塞和同步非阻塞,接下来将依次举例解释。

同步阻塞

同步阻塞就是调用方在等待另一个任务的结果返回来之前,什么事也没做,就是死等,直到返回,而且具体要等待的结果是用来干嘛的,如果不返回,是不知道的。

举例:

快到饭点了,老王很饿,来到了一家饭店,老王跟老板说来份蛋炒饭。

然后老板就是开始做,而老王就一直站在出饭的窗口等着,期间什么也没干,就是等着,直到老板把饭做好。

说明:

这种调用方式很常见,这是以前普遍的方式,流水线式调用。

如果老王就这样等着,那么效率是很低的。

同步非阻塞

同步非阻塞就是,你在等一件事A的结果时,可以继续去干另外一件事B。但是你需要时不时的回来瞧一瞧A的结果是否返回了。

程序上通常都是用轮询去获取A事件是否完成并返回结果。

举例:

快到饭点了,老王很饿,来到了一家饭店,老王跟老板说来份蛋炒饭。

然后老板就是开始做,而老王呢,就跑到饭店的门头透透气,顺便刷刷微博,但是老王需要时不时的跑进去问问老板饭好了没有

说明:

这种调用方式,一般在同步操作中,中间需要处理一个比较耗时的操作时,通常是另外开辟一个线程去处理这个比较耗时的操作,但是后边需要自己去轮询另外一个线程的执行结果是否完成。

就比如上边,饭店老板做饭比较耗时,老王并没有一直等着,而是出门刷手机,但是饭有没有做好他需要时不时的跑进去问问,需要切换自己的位置。

异步

概念

异步就是调用方不需要一直等待被依赖的操作完成,可以继续干其他事情,当被依赖的操作完成后,会自动通知调用方。

调用异步操作时,被依赖的操作会直接返回一个任务或承诺给调用方,然后调用放会继续执行后边的操作。等被依赖的操作完成后,会通知调用方

日常生活中就很常见,比如:

领导给你安排一个任务,可能会说:小明你把xx项目的方案写一下,写完之后xx项目的相关人员一起去会议室开个会。小明肯定不能立即把方案写完,此时就会回答领导,“好的领导”。然后领导继续干自己的事,小明就去写方案,写完之后小明去通知领导,然后领导拿到方案后通知相关人员一起开会。

异步阻塞

异步阻塞就是虽然被依赖项完成时会通知调用方,但是调用方并没有继续去干其他事,而是依旧继续在那等着。

举例:

快到饭点了,老王很饿,来到了一家饭店,老王跟老板说来份蛋炒饭。

老板在点菜机上下了单,并给了老王一个号,告诉老王等饭做好后,会叫号通知的。

虽然会通知,但是老王很饿很着急,依旧站在出饭窗口等着。

说明:

目前,现实社会中大部分场景都有了叫号功能,不需要一直排队等着。但是也免不了有个别人比较着急,即便是会叫号也一直站旁边等着。

异步非阻塞

异步非阻塞就是被依赖项完成时会通知调用方,调用方无需等待被依赖项,可以继续干其他跟依赖项结果无关的事。

举例:

快到饭点了,老王很饿,来到了一家饭店,老王跟老板说来份蛋炒饭。

老板在点菜机上下了单,并给了老王一个单子,单子上是5号,告诉老王饭做好后,会叫这个号通知的。

然后,老王拿着号找了个位置,刷起了新闻,期间还出门打了个电话,处理了一些工作上的事。突然老王听到叫号机通知5号的饭做好了,然后老王去窗口拿自己的饭。

说明:

这种效率是最高的,你做你的饭,我可以继续干不依赖于饭的事。你做好饭了叫我就行。

异步在目前的前后端开发中都挺常见的。

前端中通常会返回一个Promise(承诺)对象,.NET后端通常返回一个Task(任务),两个其实是一个意思。接下来以前端来举例例如:

//AService.js 有两个方法,一个是获取数据getData(),一个是做一些耗时操作doSomething()
async getData(){
    return await GetMyData()//该方法需要查数据比较耗时
}
//该方法就写一些日志
async doSomething(){
    await writeLog()
}

//B.vue页面
inint (){
    // 1 异步执行某个操作
    doSomething() 
    // 2 异步获取数据,然后对数据做xxx处理。代码的阅读和现实的语义是一样的。
    getData().then(res => {
		//可以针对res做相应的处理
    })
    //3
    //... 不依赖于1、2的同步操作。
}

//上边doSomething()和getData().then()都会立即返回一个Promise(承诺),承诺会完成.

上边1、2都是瞬间完成的,返回了一个Promise(承诺)。既然叫承诺,那就很好理解了,我承诺会完成,但不是立即完成。

就比如开会的时候领导说,接下来安排一下任务:

  1. 张三,你把A项目的方案写一下,写完跟我讲一下,我们一起开会讨论一下,张三说”好的“。此时张三只是给领导了一个承诺,并没有立即完成。(异步
  2. 李四,你等会把B项目部署一下,看看运行效果。李四说”好的“。此时李四也是一个承诺,并没有完成B项目部署。(异步
  3. 然后领导将会议记录和任务安排发了给大家。(同步)

上边的3并不依赖于1、2,领导不需要非要等张三把A项目方案写好,也不需要等李四把B项目部署好,再将会议记录和任务安排发给大家。


如果您觉得这篇文章有帮助到你,欢迎推荐。如果您觉得哪里不对,也欢迎大家拍砖讨论。

标签:异步,同步,老王,阻塞,调用,通俗,老板
来源: https://www.cnblogs.com/imlxp/p/14320293.html