0x305 同步阻塞、同步非阻塞、异步阻塞、异步非阻塞
原文:
#question 什么是同步?什么是异步?
#question 什么是阻塞 ?什么是非阻塞?
同步、异步、阻塞、非阻塞
前面已经指出了关键性的知识点,下面将直接给本文四个概念的定义。为了更好的说明,笔者做了一张图,如下:

对于主线程上执行的一系列函数,当其中的某个函数 A 需要与相关线程交互,而调用了另一个函数 a 时:
如果立即去执行函数 a,这称为同步。
如果没有去执行函数 a,而是将执行函数 a 的时机安排在未来的某个时间,然后马上继续执行函数 A,这称为异步。
当执行函数 a 时,直至获得完整的资源之前,都暂停执行当前函数,这称为阻塞。
当执行函数 a 时,立即获得瞬时的结果,然后马上继续执行当前函数。如果获得的瞬时资源不是完整的资源,之后周期性发送类似的请求,直至获得完整的资源,这称为非阻塞。
可以看出,同步与异步的区别在于函数调用的时机,而阻塞与非阻塞的区别在于发起请求后是否对本线程进行暂停。
同步阻塞、同步非阻塞、异步阻塞、异步非阻塞
很多读者(包含笔者)都喜欢作者能直截了当地给出概念,而反感拐弯抹角和旁敲侧击。因此,笔者再提炼一下本文的四个概念:
- 同步阻塞:在需要某资源时马上发起请求,并暂停本线程之后的程序,直至获得所需的资源。
- 同步非阻塞:在需要某资源时马上发起请求,且可以马上得到答复,然后继续执行之后的程序。但如果得到的不是完整的资源,之后将周期性地的请求,直至获得所需的资源。
- 异步阻塞:在需要某资源时不马上发起请求,而安排一个以后的时间再发起请求。当到了那时发出请求时,将暂停本线程之后的程序,直至获得所需的资源。在获取资源之后,使用共享信号量、异步回调等方式将结果异步反馈。
- 异步非阻塞:在需要某资源时不马上发起请求,而安排一个以后的时间再发起请求。当到了那时发出请求时,可以马上得到答复,然后继续执行之后的程序。但如果得到的不是完整的资源,之后将周期性地的请求。在最终获取到资源之后,使用共享信号量、异步回调等方式将结果异步反馈。
一个生动的例子
一个贴切生动的例子可能对理解更有帮助。这里假设了这样的一种情景:笔者正在进行公司安排的一个“cleancode”专项需求(下面简称 cleancode 专项),然后突然对于门禁上报告的一项告警不太理解,笔者想要求助自己的同事(设该同事名为 Bob),于是在公司的通信软件(设该软件名为 contact)上向其发送了此求助消息,并假设笔者每天有减脂的诉求,因此在下午下班后不会立刻去吃饭。
前述的四个概念类比如下:
同步阻塞:笔者在 contact 上给 Bob 发了一条咨询信息,并开启 contact 的消息自动弹出功能。然后笔者暂停手头的工作,翘着二郎腿开始用手机摸鱼,直到手机上弹出 contact 的关于 Bob 的回复信息。
解释:
笔者、笔者的同事 Bob:两个位于不同服务器上的操作系统。
cleancode 专项:正在“笔者操作系统”上运行的一个线程。
笔者放弃工作上的任务:cleancode 专项线程被阻塞。
笔者开始摸鱼:cleancode 专项线程因阻塞而使笔者空闲,笔者通过线程调度来运行其它无关线程。
contact 的消息自动弹出:在操作系统中,用于唤醒阻塞线程的信号量。
同步非阻塞:笔者在 contact 上给 Bob 发了一条咨询信息,然后笔者继续做 cleancode 专项中的其它内容,并周期性查看 Bob 有没有回复。
异步阻塞:笔者在日程表上记录了这个待办事项,然后笔者继续做 cleancode 专项中的其它内容,最后到下午下班时,笔者在 contact 上给 Bob 发了一条咨询信息,并开启 contact 的消息自动弹出功能。然后笔者暂停手头的工作,翘着二郎腿开始在晚上加班的时间用手机摸鱼,直到手机上弹出 contact 的关于 Bob 的回复信息。
异步非阻塞:笔者在日程表上记录了这个待办事项,然后笔者继续做 cleancode 专项中的其它内容,最后到下午下班时,笔者在 contact 上给 Bob 发了一条咨询信息,然后笔者继续加班做 cleancode 专项中的其它内容,并周期性查看 Bob 有没有回复。
异步阻塞相对于同步阻塞的意义是什么
前面已作说明,同步阻塞与异步阻塞的区别只在于执行时机不同。既然同步阻塞与异步阻塞函数都只使用一个线程,那异步阻塞相对于同步阻塞的意义是什么?为什么要使用异步阻塞?
首先,从运筹学的角度来说,合理的安排任务的执行时机是可以提高效率的,读者通过生活经验就可以判断出来。