深刻理解同步/异步与阻塞/非阻塞区别 (转)

                    转载自:http://chuansong.me/n/2124760编程

 

几年前曾写过一篇描写同步/异步以及阻塞/非阻塞的文章,最近再回头看,还存在一些理解和认知误区,因而从新整理一下相关的概念,但愿对网络编程的同行能有所启发。网络

 

同步与异步

首先来解释同步和异步的概念,这两个概念与消息的通知机制有关。
异步

 

举个例子,好比一个用户去银行办理业务,他能够本身去排队办理,也能够叫人代办,办完以后再告知用户结果。对于要办理这个银行业务的人而言,本身去办理是同步方式,而别人代办完毕再告知则是异步方式。async

 

二者的区别在于,同步的方式下,操做者主动完成了这件事情;而异步方式下,调用指令发出后,操做立刻就返回了,操做者并不能立刻知道结果,而是等待所调用的异步过程(在这个例子中是帮忙代办的人)处理完毕以后,再经过通知手段(在代码中一般是回调函数)来告诉操做者结果。函数

 

 

在上图的异步 IO 模型中,应用程序调用完 aio_read 以后,不管是否有数据可读,这个操做都会立刻返回,这个过程至关于这个例子中委托另外一我的去帮忙代办银行业务的过程,当数据读完拷贝到用户内存以后,会发一个信号通知原进程告诉读数据操做已经完成(而不只仅是有数据可读)。
spa

 

阻塞与非阻塞

接着解释阻塞与非阻塞的概念。这两个概念与程序处理事务时的状态有关。
3d

 

一样用前面的例子,当真正执行办理业务的人去办理银行业务时,前面可能已经有人排队等候。若是这我的一直从排队到办理完毕,中间都没有作过其余的事情,那么这个过程就是阻塞的,这我的当前只在作这么一件事情。orm

 



在上图中,应用程序发起 recvfrom 操做以后,要等待数据拷贝成功才能返回。整个过程当中,不能作其它的操做,这个就是典型的阻塞 IO。blog

 

反之,若是这我的发现前面排队的人很多,因而选择了出去逛逛,过了一会再回来看看有没有轮到他的号被叫到,若是没有又继续出去逛,过一阵再回来看看……如此以往,这个过程就是非阻塞的。由于处理这个事情的人,在这整个过程当中,并无作到除了这件事以外不作别的事情,他的作法是反复的过来检测,若是尚未完成就下一次再次尝试完成这件事情。进程

 

上图与前面阻塞 IO 图的区别在于,当没有数据可读时,一样的 recvfrom 操做返回了错误码,表示当前没有可读数据。换言之,即便没有数据也不会一直让这个应用阻塞在这个调用上,这就是非阻塞 IO。

 

到了这里,能够先简单的小结一下这两组概念

 

  • 阻塞与非阻塞:区别在于完成一件事情时,当事情尚未完成时,处理这件事情的人除此以外不能再作别的事情;

  • 同步与异步:是本身去作这件事情,仍是等别人作好了来通知有结果,而后再本身去拿结果。注意这里说的是拿结果,若是只是别人告诉你能够作某事,而后本身去操做,这种状况下也是同步的操做,在后面多路复用I/O中会进行阐述。

 

可见,两组概念不是一个维度的概念。咱们把须要办理银行业务的人称为 A,把代办理的人称为 B,那么在 A 委托 B 办理业务的状况下,假设 A 在交代 B 帮忙办事以后,A 就去作别的事情,那么 A 并不存在针对办理银行业务这件事情而言是阻塞仍是非阻塞,办理事务时阻塞与否,是针对真正须要办理这件事情的人,也就是这个例子里的 B。

 

与多路复用 I/O 的联系

前几年写这篇文章时,将多路复用 I/O 类的 select/poll 等和异步操做混为一谈,在这里特别作一些补充说明。

 

在之前笔者包括很多同行的理解中,就这个例子而言,列举下面状况,当去办理业务的人,须要排队时一般都会先去取号,拿到一个纸条的号码,而后等待银行叫号。在那个例子里面,曾经将银行叫号理解成 select 操做,把纸条比做向 select 注册的回调函数,一旦能够进行操做的条件知足,就会根据这个回调函数来通知办理人,而后办理人再去完成工做,所以 select 等多路复用操做是异步的行为。

 

但上面这种理解最大的错误在于,同步与异步的区别在于是否是要求办理者本身来完成,全部须要本身完成的操做都是同步操做,不论是注册了一个回调(这里的叫号小纸条)等待回调你,仍是本身一直阻塞等待。

 

在上例中,虽然对须要办理业务的人而言,经过叫号小纸条,他能够等待银行的办理通知。等待的同时能够去别的事情,好比浏览手机上网,但只要能够办理该业务的条件知足,真正叫到号能够办理业务时,办理者是须要本身去完成办理的。

 

换言之,在完成一件事情时,须要区分处理两种状态:一是这个事情是否是能够作了(条件知足的消息,如 select 告诉你某个文件描述符可读),另一个是否完成了这件事情(如调用 read/write 完成 IO 操做)。多路复用 IO 记录下来有哪些人在等待消息的通知,在条件知足时负责通知办理者,而完成这件事情仍是须要办理者本身去完成。只要是本身去完成的操做,都是同步的操做

 

UNP 的 6.2 节中,最后对异步与同步作的总结很是准确。

 

POSIX defines these two terms as follows:

 

A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes.

An asynchronous I/O operation does not cause the requesting process to be blocked.

Using these definitions, the first four I/O models—blocking, nonblocking, I/O multiplexing, and signal-driven I/O—are all synchronous because the actual I/O operation (recvfrom) blocks the process. Only the asynchronous I/O model matches the asynchronous I/O definition.

相关文章
相关标签/搜索