知识卡片
阻塞、非阻塞与同步、异步不在同一维度
内容
[[同步与异步的区别]]关注的是消息通知机制,而阻塞和非阻塞关注的是另一个完全不同的维度:程序处理事务时的状态。延续银行办事的例子:真正去办理业务的人,如果从排队到办完中间一直没做别的事情、只是干等着,这个过程就是阻塞的——对应到I/O上,应用程序发起recvfrom操作后,要一直等到数据拷贝成功才能返回,整个过程不能做别的操作,这就是典型的阻塞I/O。反过来,如果这个人发现排队的人多,选择先出去逛逛、过一会儿再回来看看轮到自己没有,没轮到就继续出去逛、过一阵再回来看——这个过程就是非阻塞的,因为处理这件事的人并没有从头到尾只守着这一件事,而是反复过来检测、没完成就下次再试。对应到I/O上,应用程序发起recvfrom后,如果当前没有数据可读,调用会直接返回一个错误码表示”当前没有可读数据”,而不会让程序一直阻塞在这个调用上,这就是非阻塞I/O。这两组概念之所以说”不在同一维度”,关键在于它们各自问的问题完全不同:同步/异步问的是”是自己去做这件事、还是等别人做完了通知你去拿结果”;阻塞/非阻塞问的是”完成这件事的过程中,当事情还没完成时,处理它的人有没有在同时做别的事”。更微妙的是,阻塞与否这个判断,必须对准”真正去办理这件事的人”,而不是”委托别人办事的人”——如果A把办业务这件事委托给B去办,A交代完就转身去做别的事情了,那么A本身根本谈不上”阻塞还是非阻塞”,因为A压根没有在等这件事;真正存在”阻塞还是非阻塞”这个状态判断的对象,是实际去执行任务的B。
结构图:
flowchart TB
subgraph 维度1["维度1:同步 vs 异步(谁去做+怎么拿结果)"]
A1["同步:自己去做\n结果自己直接拿到"]
A2["异步:委托别人做\n事后被通知取结果"]
end
subgraph 维度2["维度2:阻塞 vs 非阻塞(等待期间是否做别的事)"]
B1["阻塞:干等,期间不做别的事"]
B2["非阻塞:反复过来检测\n期间可以做别的事"]
end
维度1 -.->|"两个维度相互独立\n可以自由组合"| 维度2
C["阻塞/非阻塞的判断对象\n是真正执行任务的人(如B)\n不是委托任务的人(如A)"]
参考来源
- 位置:《高可用架构(第1卷)》第1章《高可用架构案例精选》"1.9 深入理解同步/异步与阻塞/非阻塞区别"节,"1.9.2 阻塞与非阻塞"(源文件:_epub-src/OEBPS/Text/Chapter1_9_3.xhtml)
- 结论依据:原文说明"阻塞与非阻塞:区别在于完成一件事情时,当事情还没有完成时,处理这件事情的人除此之外是否在做别的事情……可见,两组概念不在同一个维度……办理事务时阻塞与否,是针对真正需要办理这件事情的人,也就是这个例子里的B",直接支撑本卡片结论与结构图。
- 原始内容:阻塞与非阻塞:区别在于完成一件事情时,当事情还没有完成时,处理这件事情的人除此之外是否在做别的事情……办理事务时阻塞与否,是针对真正需要办理这件事情的人,也就是这个例子里的B。