阻塞/非阻塞/同步/异步详解

欢迎转载,转载请注明原文地址:http://blog.csdn.net/majianfei1023/article/details/45314803

零.导论

阻塞是不是同步,非阻塞是不是异步,他们是什么关系?刚接触网络编程的同学经常会问这种问题,而且把他们搞混,在这里我用我自己的理解详细解答一下。

想了半天,决定先讲阻塞和非阻塞,为什么呢,因为他们的时序在前面(至少我是这么理解的)。

我们以一句总结开篇,再以另一句总结结束吧。

阻塞IO和非阻塞IO的区别就在于:阻塞/非阻塞, 它们是程序在等待消息(调用函数)时的状态,应用程序的调用是否立即返回!

同步IO和异步IO的区别就在于:同步/异步, 它们是消息的通知机制,同步IO是调用完成之后返回来通知的,异步是调用完成之后不等返回,自己做自己的事,然后消息完成之后自然会有它的方式(状态、通知、回调等)来通知它。

所以,他们关注的点是不一样的,阻塞和非阻塞关注的是调用是否立即返回,同步和异步关注的是消息怎么通知给程序的。

一、阻塞与非阻塞

阻塞/非阻塞, 它们是程序在等待消息(无所谓同步或者异步)时的状态.

1. 阻塞I/O模型:

阻塞调用是指调用结果返回之前,当前线程会被挂起。函数只有在得到结果之后才会返回。

下面我用 UNP1的图来进行讲解:

如图6.1:

进程调用recvfrom向内核请求数据,内核数据并没有准备好时,不返回给进程。这时进程就阻塞在recvfrom系统调用以等待数据就绪。

阻塞函数在完成其指定的任务以前不允许程序调用另一个函数。例如,程序执行一个读数据的函数调用时,在此函数完成读操作以前将不会执行下一程序语句。当服务器运行到recvfrom语句时,而没有客户连接服务请求到来,服务器就会停止在recvfrom语句上等待连接服务请求的到来。这种情况称为阻塞(blocking)。阻塞的时候cpu不会给线程分配时间片,即线程暂停运行,但CPU可以给其他线程(或者进程)使用,并不会浪费CPU性能。

当数据没有准备好,没有返回成功(或失败)的指示之前,程序卡在recvfrom调用而不会继续往下走。直到调用返回成功(或失败)。

2.非阻塞I/O模型:

非阻塞和阻塞的概念相对应,指在不能立刻得到结果之前,该函数不会阻塞当前线程,而会立刻返回。

如图6.2:

当内核中没有数据准备好时,内核立即返回一个EWOULDBLOCK错误给应用程序,应用程序不需要把本进程投入睡眠。这样应用程序(进程)就需要不停的系统调用,也就是轮询(polling)。应用程序持续轮询内核,以查看数据是否就绪。这么做往往耗费大量CPU时间(当然你只是想查看数据有没有准备好,没准备轮询的话,那就不会了)。

看到上面两个图有什么区别吗?在等待数据阶段,

果然看图比我巴拉巴拉讲一大堆有用得多,我们仔细看,系统调用recvfrom分为两个阶段,

1.等待数据准备好的阶段(这个决定了是阻塞还是非阻塞);

2.讲数据从内核拷贝到用户空间的阶段(这个我们稍后讲,它决定了是同步还是异步)。

从图可以看出,阻塞和非阻塞的区别主要在于等待数据的时候是等待数据就绪还是立即返回,

所以:阻塞/非阻塞, 它们是程序在等待消息(无所谓同步或者异步)时的状态。(阻塞就是一直阻塞到有数据准备就绪,非阻塞就是立即返回)。

二、同步与异步

同步/异步, 它们是消息的通知机制:

1.同步IO模型:

所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回。

2.异步IO模型:

当一个异步过程调用发出后,调用者不会立刻得到结果。

实际处理这个调用的部件是在调用发出后,

通过状态、通知来通知调用者,或通过回调函数处理这个调用。

(也就是说,阻塞关注的是立即返回还是稍后返回的话,异步返回都不需要,他不关注这个,处理完会自动通知他)

我们继续看 图 6.1和图6.2,之前研究阻塞和非阻塞的时候,只顾研究他们的不同了,那么现在我们研究一下他们的相同点:看下半部分,将数据从内核复制到用户空间的时候,等到复制完成,返回给进程,进程继续进行。

那么我们再看一张图:

如图6.5,这是异步I/O模型,不用我说,大家都看到了。那么这个跟上面两张图的相同点(即:将数据从内核复制到用户空间,然后进程继续执行)有什么区别呢?

真相只有一个:

进程调用后就继续执行了(也就是我们说的,它不关注返不返回),不等数据复制到用户空间,进程继续执行了,那么数据复制到用户空间之后怎么告诉进程呢?反正内核有办法通知你数据已经处理好了,你可以选择处理了。

这个是异步,那上面自然是同步了,我们总结一下,同步和异步的区别:

同步I/O操作:导致请求进程阻塞,直到I/O操作完成(你没完成,我就看着你做,然后什么也不做,等你做完了,把东西给我);

异步I/O操作:不导致请求进程阻塞。而当你完成拷贝后,想办法通知进程就是了,它才懒得等你(所以说,异步I/O是很傲娇的,我是老大,我凭什么等你,我先做其他事,等你处理好了,打个电话告诉我)

阻塞IO和非阻塞IO的区别就在于:应用程序的调用是否立即返回!

同步IO和异步IO的区别就在于:数据拷贝的时候进程是否阻塞!

所以,简单地说,阻塞和非阻塞是指等待数据阶段,调用是否立即返回,而同步异步则是指的,复制数据的时候,我是阻塞在这里等你返回,还是我先忙其他的,等你处理好了,告诉我一声。

我再继续拿张图总结一下:

如果我们要观察 阻塞和非阻塞,观察 1和2就可以了:

程序发出调用后是否立即返回。

如果我们要观察同步和异步,观察3和4就可以了:

函数完成时进程是否阻塞(是被动等待返回,还是你主动通知)。

第一列是:同步阻塞I/O模型

第二列是:同步非阻塞I/O模型

第五列是:异步I/O模型。

对unix来讲:阻塞式I/O(默认),非阻塞式I/O(nonblock),I/O复用(select/poll/epoll)都属于同步I/O,因为它们在数据由内核空间复制回进程缓冲区时都是阻塞的(不能干别的事)。只有异步I/O模型(AIO)是符合异步I/O操作的含义的,即在1数据准备完成、2由内核空间拷贝回缓冲区后
通知进程,在等待通知的这段时间里可以干别的事。

时间: 2024-08-29 12:28:36

阻塞/非阻塞/同步/异步详解的相关文章

[Z] linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO

原文链接:http://blog.csdn.net/colzer/article/details/8169075 IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据

linux基础编程:IO模型:阻塞/非阻塞/IO复用 同步/异步 Select/Epoll/AIO(转载)

IO概念 Linux的内核将所有外部设备都可以看做一个文件来操作.那么我们对与外部设备的操作都可以看做对文件进行操作.我们对一个文件的读写,都通过调用内核提供的系统调用:内核给我们返回一个file descriptor(fd,文件描述符).而对一个socket的读写也会有相应的描述符,称为socketfd(socket描述符).描述符就是一个数字,指向内核中一个结构体(文件路径,数据区,等一些属性).那么我们的应用程序对文件的读写就通过对描述符的读写完成. linux将内存分为内核区,用户区.l

理解同步异步与阻塞非阻塞

本篇文章我准本从三个大方面来解释下同步异步.阻塞非阻塞的知识,第一个方面主要是说下,到底什么是同步异步.阻塞非阻塞:第二个方面主要是解释下在I/O场景下,同步异步阻塞非阻塞又是怎么定义的,第三个方面介绍下在unix下同步异步又有哪些阻塞非阻塞IO. 1.同步异步与阻塞非阻塞 首先从大的方面来说,"阻塞"与"非阻塞"与"同步"与"异步"不能简单的从字面理解,提供一个从分布式系统角度的回答. 1).同步与异步 同步和异步关注的是消

同步/异步与阻塞/非阻塞

一.同步与异步同步/异步, 它们是消息的通知机制 1. 概念解释A. 同步所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回. 按照这个定义,其实绝大多数函数都是同步调用(例如sin isdigit等).但是一般而言,我们在说同步.异步的时候,特指那些需要其他部件协作或者需要一定时间完成的任务.最常见的例子就是 SendMessage.该函数发送一个消息给某个窗口,在对方处理完消息之前,这个函数不返回.当对方处理完毕以后,该函数才把消息处理函数所返回的值返回给调用者. B.

理解阻塞非阻塞与同步异步

作者:严肃链接:https://www.zhihu.com/question/19732473/answer/20851256来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. "阻塞"与"非阻塞"与"同步"与"异步"不能简单的从字面理解,提供一个从分布式系统角度的回答.1.同步与异步同步和异步关注的是消息通信机制 (synchronous communication/ asynchronous c

讲一讲什么叫阻塞非阻塞同步异步

1.讲一讲什么叫阻塞非阻塞同步异步全是用来形容方法的,形容一个方法返回值状态的. 2.io读取,网络读取,jdbc读取,这些流的操作都是bio的,都是阻塞的. 3.所以沃恩一般在处理io操作时,都采用多线程来提高bio的效率. 4.io操作,就是本地文件,网络,数据嘛嘛.所以在这三种读取数据时,都要采用多线程提高效率. 5.多线程处理阻塞方法时,只不过是避免了主线程的阻塞,但是让子线程,也就是处理每个http request的线程去发生阻塞了. 6.传统的古老的开发方式: 单线程执行阻塞方法->

基础入门_Python-网络编程.分分钟掌握阻塞/非阻塞/同步/异步IO模型?

概念梳理: 故事独白: 满满爱喝茶,废话不多说,开始煮开水. 出场人物: 满满, 普通水壶, 高级水壶(水开会响) 1. 满满把水壶放在火上, 站在那里等水开(同步阻塞) 满满觉得自己有点儿傻逼~ 2. 满满把水壶放在火上,去客厅看电视,时不时的去厨房瞅瞅水开木有(同步非阻塞) 满满觉得自己还是有点傻~,于是买了个高级水壶, 水开后会响~ 3. 满满把高级水壶放在火上, 站在那里等水开(异步阻塞) 满满想高级水壶水开会自己叫~为毛不去看个电视哪? 4. 满满把高级水壶放在火上, 去客厅看电视,

同步/异步-阻塞/非阻塞

(A)同步和异步,是针对 调用结果是如何返回给调用者来说的,即调用的结果是调用者主动去获取的(比如一直等待recvfrom或者设置超时等待select),则为同步,而调用结果是被调用者在完成之后通知调用者的,则为异步(比如windows的IOCP).(B)阻塞和非阻塞,是针对调用者所在线程是否在调用之后主动挂起来说的,即如果在线程中调用者发出调用之后,再被调用这返回之前,该线程主动挂起,则为阻塞,若线程不主动挂起,而继续向下执行,则为非阻塞. 这样,在网络IO中,同步异步,阻塞非阻塞,就可以形成

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

转载自:http://chuansong.me/n/2124760 几年前曾写过一篇描写同步/异步以及阻塞/非阻塞的文章,最近再回头看,还存在一些理解和认知误区,于是重新整理一下相关的概念,希望对网络编程的同行能有所启发. 同步与异步 首先来解释同步和异步的概念,这两个概念与消息的通知机制有关. 举个例子,比如一个用户去银行办理业务,他可以自己去排队办理,也可以叫人代办,办完之后再告知用户结果.对于要办理这个银行业务的人而言,自己去办理是同步方式,而别人代办完毕再告知则是异步方式. 两者的区别在