几年前曾写过一篇描写同步/异步以及阻塞/非阻塞的文章,最近再回头看,还存在一些理解和认知误区,于是重新整理一下相关的概念,希望对网络编程的同行能有所启发。
同步与异步
首先来解释同步和异步的概念,这两个概念与消息的通知机制有关。
举个例子,比如一个用户去银行办理业务,他可以自己去排队办理,也可以叫人代办,办完之后再告知用户结果。对于要办理这个银行业务的人而言,自己去办理是同步方式,而别人代办完毕再告知则是异步方式。
两者的区别在于,同步的方式下,操作者主动完成了这件事情;而异步方式下,调用指令发出后,操作马上就返回了,操作者并不能马上知道结果,而是等待所调用的异步过程(在这个例子中是帮忙代办的人)处理完毕之后,再通过通知手段(在代码中通常是回调函数)来告诉操作者结果。
在上图的异步 IO 模型中,应用程序调用完 aio_read 之后,不论是否有数据可读,这个操作都会马上返回,这个过程相当于这个例子中委托另一个人去帮忙代办银行业务的过程,当数据读完拷贝到用户内存之后,会发一个信号通知原进程告诉读数据操作已经完成(而不仅仅是有数据可读)。
阻塞与非阻塞
接着解释阻塞与非阻塞的概念。这两个概念与程序处理事务时的状态有关。
同样用前面的例子,当真正执行办理业务的人去办理银行业务时,前面可能已经有人排队等候。如果这个人一直从排队到办理完毕,中间都没有做过其他的事情,那么这个过程就是阻塞的,这个人当前只在做这么一件事情。
在上图中,应用程序发起 recvfrom 操作之后,要等待数据拷贝成功才能返回。整个过程中,不能做其它的操作,这个就是典型的阻塞 IO。
反之,如果这个人发现前面排队的人不少,于是选择了出去逛逛,过了一会再回来看看有没有轮到他的号被叫到,如果没有又继续出去逛,过一阵再回来看看……如此以往,这个过程就是非阻塞的。因为处理这个事情的人,在这整个过程中,并没有做到除了这件事之外不做别的事情,他的做法是反复的过来检测,如果还没有完成就下一次再次尝试完成这件事情。
上图与前面阻塞 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.
http://it.dataguru.cn/article-8746-1.html
分享到:
相关推荐
理解同步/异步与阻塞/非阻塞的区别后,我们可以进一步探讨这两种机制的组合应用。 1. **同步阻塞**:最常见的组合之一,适用于简单且对实时性要求不高的应用场景。例如,使用阻塞式的方法读取文件或数据库查询。 2...
在软件开发领域,尤其是在涉及输入输出(IO)操作时,理解同步与异步、阻塞与非阻塞的概念是非常重要的。这些概念对于设计和实现高效的程序至关重要,尤其是在高并发和分布式系统中。 一、同步与异步 同步和异步是...
总结来说,理解异步、同步、阻塞和非阻塞的概念对于优化程序性能、提高系统并发性和减少资源浪费至关重要。在实际编程中,开发者需要根据具体场景选择合适的方法,平衡效率和复杂性。例如,对于用户界面操作,异步...
Socket编程中的阻塞与非阻塞、同步与异步是两个独立的概念,它们涉及的是不同层面的操作机制。这里我们将详细探讨这两个概念以及I/O模型。 首先,同步与异步是客户端(C端)调用服务端(S端)时的行为模式。同步...
同步异步阻塞非阻塞 IO 模型 在 Linux 环境下的网络 IO 中,有五种基本的 IO 模型:阻塞 IO、非阻塞 IO、IO 多路复用、信号驱动 IO 和异步 IO。其中,信号驱动 IO 不常用,因此主要介绍其余四种 IO 模型。 1. 阻塞...
tcp socket同步 异步 阻塞 非阻塞 的解释.zip 基本概念:同步、异步、阻塞和非阻塞的区别 同步异步与阻塞非阻塞的区别 C++ 同步异步与阻塞非阻塞的区别
同步、异步、阻塞与非阻塞 在计算机科学中,同步、异步、阻塞与非阻塞是四个紧密相关的概念,它们都是关于任务或进程之间的交互和通信方式的描述。下面将对这四个概念进行详细的介绍和比较。 同步(Synchronous) ...
Java 同步、异步、阻塞和非阻塞分析 Java 中的同步、异步、阻塞和非阻塞是四个相关但不同的概念,它们都是在多线程编程中解决耗时操作的方法。在这里,我们将详细介绍这些概念之间的区别和联系。 同步...
### 同步与异步——阻塞与非阻塞型IO详解 #### 一、引言 在计算机科学中,I/O(输入/输出)操作是任何程序与外部世界交互的基础。根据I/O操作的不同特性,可以将其分为四大类:同步阻塞IO、同步非阻塞IO、异步阻塞...
常规的误区 ... ... 这个时候你问别人,刚刚代码发起的这个请求是不是一个同步请求,对方一定回答是。这是对的,它确实是。...对方一定是这样回答的,“因为发起... 不是因为代码卡住不动了才叫同步请求,而是因为它是同步
在计算机编程,特别是网络编程中,同步、异步、阻塞和非阻塞是四个关键的概念,它们描述了程序执行时处理任务的方式。 同步是一种调用模式,它要求调用者在等待结果返回之前不能继续执行其他任务。例如,当你调用`...
### 一文理解异步同步阻塞与非阻塞 #### 同步与异步 在探讨异步和同步的概念前,我们首先需要明确这两者的区别。同步与异步主要关注的是消息通信机制,即synchronous communication 和 asynchronous communication...
在Java编程中,同步、异步、阻塞和非阻塞是四个重要的概念,它们涉及到多线程和并发处理,特别是在网络编程中尤为关键。理解这些概念有助于优化程序性能和提高资源利用率。 1. **同步**: 同步是编程中一种控制机制...
总结来说,理解同步、异步、阻塞和非阻塞的概念对于编写高效并发代码至关重要。在实际编程中,根据场景选择合适的策略,可以极大地提高系统的响应速度和资源利用率。Java等编程语言提供了丰富的工具和库来支持这些...
JAVA 同步、异步、阻塞和非阻塞之间的区别 在软件开发中,同步、异步、阻塞和非阻塞都是非常重要的概念,它们之间的区别是很多开发者经常混淆的。今天,我们将详细介绍JAVA同步、异步、阻塞和非阻塞之间的区别。 ...
用一个最简单的例子说明异步非阻塞Socket的基本原理和工作机制
在计算机科学中,同步、异步、阻塞和非阻塞是并发编程中的核心概念,它们关乎程序如何处理数据输入/输出(I/O)操作。这些概念的理解对于编写高效的并发应用至关重要。 同步与异步主要关注的是数据处理的顺序和控制...
在讨论同步与异步时,往往也会涉及到阻塞(Blocking)与非阻塞(Non-blocking)的概念。这两个概念与同步/异步密切相关,但又有所区别: - **阻塞调用**: 指的是调用的结果返回之前,当前线程会被挂起。即使没有...
如果在非主线程中使用,记得使用异步方式,以避免阻塞UI。 异步加载组件是处理大组件或网络加载资源时的最佳实践。对于`Loader`,你可以通过监听其`status`属性的变化来实现异步加载: ```qml Loader { id: ...