同步、异步、堵塞、非堵塞和函数调用及I/O之间的组合概念

时间:2022-06-17
本文章向大家介绍同步、异步、堵塞、非堵塞和函数调用及I/O之间的组合概念,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

        在我们工作和学习中,经常会接触到“同步”、“异步”、“堵塞”和“非堵塞”这些概念,但是并不是每个人都能将它们的关系和区别说清楚。本文将对这些基本概念进行讨论,以期让大家有更清楚的认识。(转载请指明出于breaksoftware的csdn博客)

        IT技术和相关术语均为舶来品,于是其相关的问题也并非只有我们讲中文的分不清。在一些外文网站上,我们可以发现外国人也会对这些概念进行区分和探讨。于是,我觉得通过一些英文资料来解释这些问题比较合适,毕竟从语言的角度说,它们更贴近问题的起源。

        对于资料的选择,我优先选择相信大家公认的一些权威资料。比如RFC标准是最高的;其次是一些权威专家的论著,比如Addison Wesley的《UNIX Network Programming》;再其次是一些权威网站上的信息,比如百度百科、维基百科、IBM或者微软官网上一些论述。

        为了把问题说清楚,我决定先去探讨意思相对的概念。比如“同步”和“异步”就是相对的概念,因为我们从来不会说这是一个“同步异步……”;同样“堵塞”和“非堵塞”也是一对相对的概念,我们也不会说那是一个“堵塞非堵塞……”。然后我们将探讨这两对相对的概念的区别,比如“同步”和“堵塞”的区别,“异步”和“非堵塞”的区别。最后我们将结合“函数调用”和“I/O”来探讨组合出的概念。

同步/异步

同步

        “同步”这个概念的探讨将非常有意思,因为我们从这个词可以感受下外语翻译成中文后产生的偏差。         现在我们先“忘记”自己是IT从业人员,“同步”对我们来说可以按百度百科中的解释为:

同步指两个或两个以上随时间变化的量在变化过程中保持一定的相对关系。

        怎么具体化这个解释呢?比如战争中,一个集团军的统帅命令自己部下左、中、右三军“同步”前进。于是我们补脑一下,可以想象出同在一个时间段内,三个不同的个体在同时做三件事,而这三个个体存在一定的关联性——同时听命于集团军的统帅。于是这就产生了一种混乱,当我们学习了IT技术,特别是了解了“线程”概念后,可能马上把集团军的统帅想成一个“进程”,而三个“同步”前进的军队就是三个“线程”。那么此时“同步”是不是就是指若干个个体同时发生变化且存在一定关联性呢?是不是更像“Asynchronous”的概念?其实这个问题并非我的臆测,之前在学校时,经常有同学将“同步”的概念理解成“Asynchronous”的行为特点,而我也曾被它们弄混淆过。         虽然我没有去考证过,但是我觉得上面对“同步”的解释更加符合普通民众的认知。         然后不知何时“Synchronization”也被翻译成“同步”了。于是我们在百度百科里看到如下的解释

    同步(英语:Synchronization),指对在一个系统中所发生的事件(event)之间进行协调,在时间上出现一致性与统一化的现象。在系统中进行同步,也被称为及时(in time)、同步化的(synchronous、in sync)。

        其实这段解释和维基百科中对“Synchronization”解释是一致的

    Synchronization is the coordination of events to operate a system in unison. The familiar conductor of an orchestra serves to keep the orchestra in time. Systems operating with all their parts in synchrony are said to be synchronous or in sync; those which are not are asynchronous.

        这个解释并不是我们关注的重点,因为它和我们探讨的重心没太多关系。我引入它只是为了说明“Synchronization”也被翻译成“同步”这样一件事的存在。

        然而,维基百科里还有一段关于计算机术语中“Synchronization”的解释,它被拿到一个单独的页面中解释——足以说明它和传统意义上“Synchronization”的不同

    In computer science, synchronization refers to one of two distinct but related concepts: synchronization of processes, and synchronization of data. Process synchronization refers to the idea that multiple processes are to join up or handshake at a certain point, in order to reach an agreement or commit to a certain sequence of action. Data synchronization refers to the idea of keeping multiple copies of a dataset in coherence with one another, or to maintain data integrity. Process synchronization primitives are commonly used to implement data synchronization.

        这段解释将“同步”分为两种:数据同步和过程同步。数据同步不是我们讨论的重点,所以忽略。过程同步(至于此处翻译成“进程”还是“过程”,我觉得“过程”所以可以更加宽泛些而且合理,所以选用“过程”一词)是指多个过程通过一定组织方式达到某种协调,这种协调包含“按一定顺序执行”。这种解释就非常像我们IT民工理解中的“synchronous”了。可惜汉语中“同步”至少在字面上是没有这层意思的。

异步

       “异步”这个词在汉语中应该没有历史包袱,所以它的表意和英语中“asynchronous”一致。于是没什么好讨论的。唯一有意思的是这个词是如何被选中来表示“asynchronous”的。可能是因为“synchronous”和“asynchronous”在英语中意思相反,而中文中已经找到“同步”来翻译“synchronous”,于是取“同”相反的修饰词“异”来翻译“asynchronous”为“异步”。         在维基百科上,我找到“Asynchrony”一词的解释,其含义可以解释“asynchronous”

    Asynchrony, in computer programming, refers to the occurrence of events independently of the main program flow and ways to deal with such events. These may be "outside" events such as the arrival of signals, or actions instigated by a program that take place concurrently with program execution, without the program blocking to wait for results

堵塞/非堵塞

堵塞

        堵塞(Blocking)在维基百科中的解释如下:

    In computing, a process is an instance of a computer program that is being executed. A process always exists in exactly one process state. A process that is blocked is one that is waiting for some event, such as a resource becoming available or the completion of an I/O operation.

        其意思是过程需要等待一个事件的变化而处于某个状态中。这个事件可以是个资源,比如:内存、CPU、网络、磁盘等

    In a multitasking computer system, individual tasks, or threads of execution, must share the resources of the system. These resources might be:
	• the CPU
	• network
	• memory
	• disk        

非堵塞

        我在维基百科上没有找到“非堵塞(Non-blocking)”的词条,但是找到一个类似的“Non-blocking algorithm

In computer science, an algorithm is called non-blocking if failure or suspension of any thread cannot cause failure or suspension of another thread

同步/异步和堵塞/非堵塞

        假如我们只有上述知识,还是很难将“同步”和“堵塞”分清楚,也不太能说清“异步”和“非堵塞”的区别。目前我看国内很多论坛上关于这个问题的讨论也显得前后矛盾。

        为了把概念区分开,我们可以借鉴下Addison Wesley的《UNIX Network Programming》中关于同步I/O和异步I/O的一个讨论:

        Synchronous I/O versus Asynchronous I/O         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 modelsblocking, nonblocking, I/O multiplexing, and signal-driven I/Oare all synchronous because the actual I/O operation (recvfrom) blocks the process. Only the asynchronous I/O model matches the asynchronous I/O definition.

        其大意是“同步I/O”要求过程堵塞直到I/O操作完成。后面我们会讲到,即使使用O_NONBLOCK修饰的I/O,也会因为在调用read等函数时,需要等待内核层把读取的数据运输到用户层。于是I/O操作的完成(completes)与否要视数据是否全部进入用户层。

        也就是说“同步”强调的是操作最终完成了,而非中间状态。“堵塞”强调的是对系统资源的等待。相应的,“异步”强调的是操作没有完成,处于中间状态。“非堵塞”强调的是没有对系统资源产生等待行为。之后我们将结合他们和“函数调用”及“I/O”的组合概念来加以区分。

同步/异步、堵塞/非堵塞和函数调用

         以下图为例,1、2的操作我们可以认为是“非堵塞的”,我们称之为“非堵塞调用”或者“异步调用”;3操作需要把数据从内核态运送到用户态,于是发生资源等待,从而发生堵塞,我们可以称之为“堵塞调用”或者“同步调用”(整个操作完成)。以更高的视角来看,1、2和3这一组操作最终达到的是一个“同步调用”的结果。

        可见“同步调用”是由“堵塞的调用”和“非堵塞的调用”组成,其过程可以没有“非堵塞的调用”,但是必须至少有一个“堵塞的调用”。而“异步调用”和“非堵塞调用”则可以视为一个意思。

同步/异步、堵塞/非堵塞和I/O

        这块的讨论我将结合Addison Wesley的《UNIX Network Programming》和IBM官网的《Boost application performance using asynchronous I/O》

        选用Addison的论著无可厚非,毕竟他是大牛,而且《UNIX Network Programming》还是经典之作。选用《Boost application performance using asynchronous I/O》则是因为它在国内被很多人翻译成了中文,之后的示例图也都源于这篇文章,而我对其解释持保留看法。

 堵塞I/O       

        堵塞I/O是默认的I/O类型,因为它不需要使用O_NONBLOCK去修饰。以I/O读取为例,在用户态read函数会一直等待内核态返回结果。这种模型还可称为“同步堵塞模型”

非堵塞I/O

        非堵塞I/O需要使用O_NONBLOCK去修饰。这样在操作该I/O时,如果系统尚未将数据准备好,则直接从内核态返回一个错误。如果数据准备好了,则用户态会等待内核将数据输送到用户态。这种模型可以称之为“同步非堵塞模型”,因为从整个操作来看,这是个同步I/O。而从IO自身来看,因为被O_NONBLOCK修饰,所以是非堵塞的。

多路复用I/O

        不管I/O是否被O_NONBLOCK修饰,遇到select/poll方法都会被堵塞。所以多路复用I/O可以是“同步堵塞模型”,也可以是“同步非堵塞模型”

        但是在《Boost application performance using asynchronous I/O》一文(后称《Boo》文)中,将使用O_NONBLOCK修饰的多路复用模型称之为“Asynchronous blocking I/O”,这个观点我是不认可的。

        为什么呢?当我们定义一个名称时,前面的定语可能用于修饰不同的概念。如果按照《Boo》文描述,Asynchronous应该是用于修饰I/O的,Blocking是用于修饰Select函数调用的。但是之前我们讲过,Addison Wesley根据RFC对Synchronous I/O的定义,认定多路复用I/O不属于异步IO。同样,如果Asynchronous不是修饰I/O,那么Blocking是用于修饰I/O的么?那当然更不对,因为I/O被O_NONBLOCK修饰了。那如果Asynchronous和Blocking都不是修饰I/O的,那么Asynchronous blocking I/O和Synchronous non-blocking I/O又有什么区别呢?

异步I/O

        这种I/O在Linux系统上叫AIO,在windows系统上交IOCP(完成端口)。这种模型最大的特征执行用户态响应前,数据已经进入用户态,从而不会发生像同步I/O一样,需要等待内核态往用户态输送数据。这种模型也称“异步非堵塞模型”

参考链接:

http://library.tebyan.net/en/Viewer/Text/164873/92#ch06fig01

https://www.ibm.com/developerworks/library/l-async/

https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean

http://www.programmr.com/blogs/difference-between-asynchronous-and-non-blocking

https://stackoverflow.com/questions/8416874/whats-the-differences-between-blocking-with-synchronous-nonblocking-and-asynch

https://blogs.msdn.microsoft.com/csliu/2009/08/27/io-concept-blockingnon-blocking-vs-syncasync/

http://www.cs.unc.edu/~dewan/242/s07/notes/ipc/node9.html

https://coelhorjc.wordpress.com/2014/12/18/using-non-blocking-and-asynchronous-io-ck10-problem-in-linux-and-windows-with-epool-iocp-aiolibaio-libeventlibevlibuv-boost-asio/

http://www.cnblogs.com/whyandinside/archive/2012/03/04/2379234.html

http://www.fsl.cs.sunysb.edu/~vass/linux-aio.txt

https://stackoverflow.com/questions/2625493/asynchronous-vs-non-blocking

http://blog.csdn.net/historyasamirror/article/details/5778378

http://www.dart.com/help/ptsslnet/UsingSynchronousVsAsynchronous.html

https://en.wikipedia.org/wiki/Asynchronous_method_invocation