本文从编程的角度解释同步、异步、阻塞、非阻塞的定义,以及它们之间的联系。
一、定义
1)同步
同步是指主程序在发起一个函数调用时,该函数只有等到任务完成后才会返回执行结果(return)。
主程序在等待结果期间:
如果主程序是阻塞的,那么将完全不能干其它事情;
如果主程序是非阻塞的,那么只能做一件事,就是不停轮询查看任务是否已完成。
2)异步
异步是指主程序在发起一个函数调用时,该函数在任务完成前就会返回,但返回的通常是一个中间结果,例如返回一个“任务正在处理中”的结果给主程序,等到任务完成后,函数会通过回调的方式通知主程序。主程序在拿到中间结果后,如果主程序是非阻塞的,那么主程序可以去干其它事情。
3)阻塞
阻塞是指主程序在等待任务结果期间,线程会被挂起(得不到CPU的调度),完全不能干其它事情。
4)非阻塞
非阻塞是指主程序在等待任务结果期间,线程不会被挂起(能得到CPU的调度)。如果函数是同步调用的话,期间主程序只能不断地轮询查看任务是否已完成,除此以外不能干其它事情;如果是异步调用的话,则可以自由的去干其它事情。
二、组合场景
下面以“小明向书店老板询问是否有某一本书”这个场景来举例。
1)同步阻塞
小明问书店老板是否有某一本书,于是老板进去仓库一本一本的找,直至得到结果后才出来告诉小明(同步)。在老板出来前,小明在原地睡觉(阻塞,相当于线程被挂起),得到答复后才会醒来。
2)同步非阻塞
小明问书店老板是否有某一本书,于是老板进去仓库一本一本的找,在得到答复前,小明没有睡觉(非阻塞,相当于线程没有被挂起)。虽然没有睡觉,但是期间小明只能做一件事,就是在原地不停的询问仓库里的老板:“你找完了没有”,只有老板回复说找完了(任务完成了),小明才能继续干其它事情,这也是同步的含义要求。
3)异步阻塞
异步阻塞这种模型在实际应用中非常罕见,因为它的设计理念存在矛盾:异步的目的是让调用者不必等待任务完成,而阻塞却会让调用者等待。这两者的结合通常没有明显的优势,甚至可能导致效率低下。
4)异步非阻塞
小明问书店老板是否有某一本书,老板说:“我去仓库里面找一下,得到答案后通过电话通知你”(异步,先返回中间结果,后续通过回调方式通知主程序)。然后小明就出去逛街干其它事去了(非阻塞)
三、总结
同步、异步关注的是函数返回的时机,在任务完成后才返回就是同步,在任务完成前就返回则是异步;
阻塞、非阻塞关注的是程序在等待结果期间的线程状态,线程被挂起了则是阻塞,没有被挂起则是非阻塞。