最近参与了一个服务器异步化改造的项目,对异步化的理解又多了一些。正好这周还没有写东西,那就借这个话题谈谈同步异步和阻塞非阻塞。
刚开始接触这几个概念的时候,本人也是很容易把他们弄混。这主要是由于网上的资料很多都把这两组名词混在一起讲。其实硬要说这两组名词有什么联系的话,那就是阻塞和非阻塞都是同步,而异步就只是异步。
这里讨论的主要都是网络I/O环境,建议大家读一下Richard Stevens的“UNIX® Network Programming Volume 1, Third Edition: The Sockets Networking ”,6.2节“I/O Models ”,书中对各种I/O进行了详细的讲解,读完之后对各种I/O就能有个比较完整的认识了。
首先要明确一下,一次I/O操作其实可以分为两个阶段:
1.数据准备阶段,等待需要的数据到位
2.数据拷贝阶段,将数据拷贝到需要的进程中
同步和异步
同步I/O就是在本次I/O操作完成之前,进程被阻塞在那里。注意这里并没有说是在哪个阶段被阻塞。
异步I/O就是进程不会被阻塞,也就是说进程可以同时进行多个I/O操作。
可以看到同步I/O相当于一心一意只做一件事情,直到这件事情做完了。而异步I/O就是“三心二意”,同时做好多件事。谁好谁坏真的不能一言以蔽之,要根据具体的使用场景来决定用哪种I/O。
阻塞和非阻塞
阻塞I/O就是在数据准备阶段就被阻塞了,直到这次I/O操作结束为止。
非阻塞I/O就比阻塞的要“聪明”一点,它在数据准备阶段会先询问数据是否准备好了,如果没有准备好系统会返回一个错误告诉它。这样它就不会等在那里,而是每隔一段时间就去询问一下直到数据准备就绪。不过数据拷贝阶段依然还是会被阻塞。但这样比阻塞I/O来说被阻塞的时间变短了。
阻塞和非阻塞的区别就是一个“守株待兔”,而另一个“投石问路”。不过既然阻塞和非阻塞I/O都会被阻塞,那也就是说它们都属于同步I/O的范畴内。
最后举一个例子来说明,这个脱胎于在知乎上看到的一个比喻,觉得很好:
有A,B,C三个人去书店买书,
A得知书没有了,所以他就在书店住下了,直到书到货了买到书为止(这只是个比喻。。。)
B得知书没有了,他就回家了。然后每天都来问一次,直到书到货了买到了书。
C得知书没有了,他给书店留了一个电话,这样等书到货了,书店打电话通知他,他再来买书就可以了。
A是阻塞,B是非阻塞,C是异步,而A和B都是同步。