<同步,异步>与<阻塞,非阻塞>的区别?

426 views
Skip to first unread message

麻油蒜泥

unread,
Aug 9, 2011, 3:08:27 AM8/9/11
to TopLanguage
去年面试的时候被问到了一个问题:你觉得<同步,异步>与<阻塞,非阻塞>两组概念之间有什么区别?

当时我答得比较烂,大概就是举了些例子,比如线(进)程的同步,以及系统调用的阻塞非阻塞。它们之间真正的区别从来没有完全梳理清楚过。哪位网友能够给
一个比较清晰的解释?

Bearice Ren

unread,
Aug 9, 2011, 3:27:05 AM8/9/11
to pon...@googlegroups.com
因为出现了"阻塞”,所以假设这里的同步和异步指IO过程中的术语,而不是进程/线程间同步的概念。

在IO过程中,同步请求是指数据缓存在被内核使用完之后才返回的模型,比如常用的read()和write().
而异步请求是指在系统调用返回后,提供的缓存仍然会被内核使用的模型,比如 Windows 的 IOCP.
而阻塞与非阻塞是指内核如何通知IO事件完成的过程。阻塞时系统调用仅仅在IO完成时返回,而非阻塞是立刻返回。
但是是否同步和阻塞和非阻塞无关,例如read()函数既可以作用于阻塞fd也可以作用于非阻塞fd.

这些就是我对此的理解,如果有错误希望大家能指正,
--
以上内容完全是复制粘贴,本人并不明白其意思,故本人不对以上内容负法律责任,请不要跨省追捕。要详查请自己联系原作者,谢谢!
Bearice@Guilin, Guangxi, China. Web:http://blog.icybear.net
一头宅熊、开源支持者、P2P拥护者; Google粉,FF粉,桂林米粉;翻墙运动爱好者;马勒戈壁驻桂办事处干事;最近添加眼镜属性(据说原因是很萌)。

linux JHON

unread,
Aug 9, 2011, 4:45:39 AM8/9/11
to pon...@googlegroups.com
同步在进程和线程之间存在,也同样存在于IO。但是根据这里的上下文,应该问的是IO的同步。线程或进程的同步和互斥是另外一个话题了。

阻塞和非阻塞很好区别,所谓阻塞就是系统调用在IO调用完成时才返回,被阻塞的进程处于睡眠状态。
非阻塞IO是指不管系统调用是否完成都立刻返回,不会导致进程挂起。服务器的设计中都使用非阻塞IO,用于响应高并发的连接请求。
这里还有个概念就是IO复用,其实是阻塞到select或poll等这样的系统调用,而不是真正的read或write。

同步和异步IO:下面是POSIX的定义
所谓同步IO就是请求进程阻塞到直到IO操作完成时。阻塞IO和非阻塞IO都是同步IO。
异步IO就是IO操作不会引起请求进程的阻塞。

下面的话引自UNPv1
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.

在 2011年8月9日 下午3:08,麻油蒜泥 <gin.y...@gmail.com> 写道:

jaywong

unread,
Aug 9, 2011, 9:58:43 PM8/9/11
to pon...@googlegroups.com

IO模型

    目前unix存在五种IO模型(这也和上一篇文章:Unix IO 模型 中提到的一致),分别是:

  • 阻塞型 IO(blocking I/O)
  • 非阻塞性IO(nonblocking I/O)
  • IO多路复用(I/O multiplexing)
  • 信号驱动IO(signal driven I/O)
  • 异步IO(asynchronous I/O)

IO的两个阶段

  • 等待数据准备好
  • 将数据从内核缓冲区复制到用户进程缓冲区

同步,异步的区别

    那么究竟什么是同步和异步的区别呢?请重点读一下原文6.2节中的信号驱动IO和异步IO中的比较。最后总结出来是:

  • 同步IO,需要用户进程主动将存放在内核缓冲区中的数据拷贝到用户进程中。
  • 异步IO,内核会自动将数据从内核缓冲区拷贝到用户缓冲区,然后再通知用户。

    这样,同步和异步的概念就非常明显了。以上的五种IO模型,前面四种都是同步的,只有第五种IO模型才是异步的IO。

阻塞和非阻塞

    那么阻塞和非阻塞呢?注意到以上五个模型。阻塞IO,非阻塞IO,只是上面的五个模型中的两个。阻塞,非阻塞,是针对单个进程而言的。

    当对多路复用IO进行调用时,比如使用poll。需注意的是,poll是系统调用,当调用poll的时候,其实已经是陷入了内核,是内核线程在跑了。因此对于调用poll的用户进程来讲,此时是阻塞的。

    因为poll的底层实现,是去扫描每个文件描述符(fd),而如果要对感兴趣的fd进行扫描,那么只能将每个描述符设置成非阻塞的形式(对于用户进程来讲,设置fd是阻塞还是非阻塞,可以使用系统调用fcntl),这样才有可能进行扫描。如果扫描当中,发现有可读(如果可读是用户感兴趣的)的fd,那么select就在用户进程层面就会返回,并且告知用户进程哪些fd是可读的。

    这时候,用户进程仍然需要使用read的系统调用,将fd的数据,从内核缓冲区拷贝到用户进程缓冲区(这也是poll为同步IO的原因)。

    那么此时的read是阻塞还是非阻塞呢?这就要看fd的状态了,如果fd被设置成了非阻塞,那么此时的read就是非阻塞的;如果fd被设置成了阻塞,那么此时的read就是阻塞的。

    不过程序已经执行到了这时候,不管fd是阻塞还是非阻塞,都没有任何区别,因为之前的poll,就是知道有数据准备好了才返回的,也就是说内核缓冲区已经有了数据,此时进行read,是肯定能够将数据拷贝到用户进程缓冲区的。

    但如果换种想法,如果poll是因为超时返回的,而我们又对一个fd(此fd是被poll轮询过的)进行read调用,那么此时是阻塞还是非阻塞,就非常有意义了,对吧!

结论

  • 判断IO是同步还是异步,是看谁主动将数据拷贝到用户进程。
  • select或者poll,epoll,是同步调用,进行此调用的用户进程也处于阻塞状态。
  • javaScript或者nodejs中的读取网络(文件)数据,然后提供回调函数进行处理,是异步IO。

  • from http://blogread.cn/it/article.php?id=4108&f=sinat

-- 
jaywong
已使用 Sparrow 发送
已使用 Sparrow 发送

李玉林

unread,
Aug 9, 2011, 10:06:40 PM8/9/11
to pon...@googlegroups.com

yuan zhu

unread,
Aug 10, 2011, 2:38:23 AM8/10/11
to pon...@googlegroups.com
这话就是一个术语,一个行话,不一定硬要往io操作上面套。

阻塞与非阻塞,取决于该函数调用是否可能导致当前用户态线程sleep?

同步与异步,取决于该函数调用的结果(这里的“结果”不仅仅指返回值,还可能包含其它信息),是在函数返回的时机获取呢,还是通过另外一个上下文进行通知?

没事瞎琢磨,纯属个人意见,欢迎拍砖。

On 8/10/11, 李玉林 <yulin...@gmail.com> wrote:
> IO - 同步,异步,阻塞,非阻塞 (亡羊补牢篇) - 智障大师 的专栏 -

> CSDN博客<http://blog.csdn.net/historyasamirror/article/details/5778378>


>
> 在 2011年8月10日 上午9:58,jaywong <jaywon...@gmail.com>写道:
>
>> IO模型
>>

>> 目前unix存在五种IO模型(这也和上一篇文章:Unix IO 模型 <http://www.zavakid.com/70>


>> 中提到的一致),分别是:
>> 阻塞型 IO(blocking I/O)
>> 非阻塞性IO(nonblocking I/O)
>> IO多路复用(I/O multiplexing)
>> 信号驱动IO(signal driven I/O)
>> 异步IO(asynchronous I/O) IO的两个阶段
>> 等待数据准备好
>> 将数据从内核缓冲区复制到用户进程缓冲区同步,异步的区别
>>
>>

>> 那么究竟什么是同步和异步的区别呢?请重点读一下原文<http://u.115.com/file/bh06p2sr#UNIX_Network_Programming.chm>


>> 6.2节中的信号驱动IO和异步IO中的比较。最后总结出来是:
>> 同步IO,需要用户进程主动将存放在内核缓冲区中的数据拷贝到用户进程中。
>> 异步IO,内核会自动将数据从内核缓冲区拷贝到用户缓冲区,然后再通知用户。
>>
>> 这样,同步和异步的概念就非常明显了。以上的五种IO模型,前面四种都是同步的,只有第五种IO模型才是异步的IO。
>> 阻塞和非阻塞
>>
>> 那么阻塞和非阻塞呢?注意到以上五个模型。阻塞IO,非阻塞IO,只是上面的五个模型中的两个。阻塞,非阻塞,是针对单个进程而言的。
>>
>>
>>
>> 当对多路复用IO进行调用时,比如使用poll。需注意的是,poll是系统调用,当调用poll的时候,其实已经是陷入了内核,是内核线程在跑了。因此对于调用poll的用户进程来讲,此时是阻塞的。
>>
>>
>>
>> 因为poll的底层实现,是去扫描每个文件描述符(fd),而如果要对感兴趣的fd进行扫描,那么只能将每个描述符设置成非阻塞的形式(对于用户进程来讲,设置fd是阻塞还是非阻塞,可以使用系统调用fcntl),这样才有可能进行扫描。如果扫描当中,发现有可读(如果可读是用户感兴趣的)的fd,那么select就在用户进程层面就会返回,并且告知用户进程哪些fd是可读的。
>>
>> 这时候,用户进程仍然需要使用read的系统调用,将fd的数据,从内核缓冲区拷贝到用户进程缓冲区(这也是poll为同步IO的原因)。
>>
>>
>>
>> 那么此时的read是阻塞还是非阻塞呢?这就要看fd的状态了,如果fd被设置成了非阻塞,那么此时的read就是非阻塞的;如果fd被设置成了阻塞,那么此时的read就是阻塞的。
>>
>>
>>
>> 不过程序已经执行到了这时候,不管fd是阻塞还是非阻塞,都没有任何区别,因为之前的poll,就是知道有数据准备好了才返回的,也就是说内核缓冲区已经有了数据,此时进行read,是肯定能够将数据拷贝到用户进程缓冲区的。
>>
>>
>>
>> 但如果换种想法,如果poll是因为超时返回的,而我们又对一个fd(此fd是被poll轮询过的)进行read调用,那么此时是阻塞还是非阻塞,就非常有意义了,对吧!
>> 结论

>> 判断IO是同步还是异步,是看谁主动将*数据*拷贝到用户进程。


>> select或者poll,epoll,是同步调用,进行此调用的用户进程也处于阻塞状态。
>> javaScript或者nodejs中的读取网络(文件)数据,然后提供回调函数进行处理,是异步IO。
>>
>> from http://blogread.cn/it/article.php?id=4108&f=sinat
>>
>> --
>> jaywong

>> 已使用 Sparrow <http://www.sparrowmailapp.com/?sig> 发送
>> 已使用 Sparrow <http://www.sparrowmailapp.com/?sig> 发送

yuan zhu

unread,
Aug 10, 2011, 2:47:55 AM8/10/11
to pon...@googlegroups.com
修正一下:同步与异步,取决于该函数调用的结果(这里的“结果”不仅仅指返回值,还可能包含其它信息),是在函数返回的时机获取呢,还是通过另外一个上下文进行通知?

改正为:同步与异步,取决于该函数调用的功能完成后的结果(这里的“结果”不仅仅指返回值,还可能包含其它信息),是在函数返回的时机获取呢,还是通过另外一个上下文进行通知?

加上“完成”等关键字,方便熟悉windows完成端口模型的朋友理解。

另外比较狭义一点去理解“异步”(其实也是最常见的一种)的话,上文所述的“通过另外一个上下文进行通知”一定是发生了内核线程向用户线程的通信请求。

广义一点来看,投射消息到消息队列然后消息队列再派发消息到消息泵去处理这个典型模型也算得上“异步”。

Tomas Huang (冠)

unread,
Aug 11, 2011, 11:51:17 PM8/11/11
to pon...@googlegroups.com

感觉你没有对阻塞非阻塞进行解释啊,请问为什么nodejs宣称是非阻塞的呢?

Alex

unread,
Aug 13, 2011, 5:12:21 AM8/13/11
to TopLanguage
我的理解是:
同步和异步所说的对象是:它要完成的工作。

阻塞和非阻塞所说的对象是:执行该operation所在的进程。

On 8月12日, 上午11时51分, Tomas Huang (冠) <huangguan3112...@gmail.com>
wrote:
> 感觉你没有对阻塞非阻塞进行解释啊,请问为什么nodejs宣称是非阻塞的呢?


> 在 2011-8-10 上午9:58,"jaywong" <jaywong.sm...@gmail.com>写道:
>
>
>
>
>
>
>
>
>
> > IO模型
>
> > 目前unix存在五种IO模型(这也和上一篇文章:Unix IO 模型 中提到的一致),分别是:
>
> > 阻塞型 IO(blocking I/O)
> > 非阻塞性IO(nonblocking I/O)
> > IO多路复用(I/O multiplexing)
> > 信号驱动IO(signal driven I/O)
> > 异步IO(asynchronous I/O)
> > IO的两个阶段
> > 等待数据准备好
> > 将数据从内核缓冲区复制到用户进程缓冲区
> > 同步,异步的区别
>
> > 那么究竟什么是同步和异步的区别呢?请重点读一下原文6.2节中的信号驱动IO和异步IO中的比较。最后总结出来是:
>
> > 同步IO,需要用户进程主动将存放在内核缓冲区中的数据拷贝到用户进程中。
> > 异步IO,内核会自动将数据从内核缓冲区拷贝到用户缓冲区,然后再通知用户。
>
> > 这样,同步和异步的概念就非常明显了。以上的五种IO模型,前面四种都是同步的,只有第五种IO模型才是异步的IO。
>
> > 阻塞和非阻塞
>
> > 那么阻塞和非阻塞呢?注意到以上五个模型。阻塞IO,非阻塞IO,只是上面的五个模型中的两个。阻塞,非阻塞,是针对单个进程而言的。
>

> 当对多路复用IO进行调用时,比如使用poll。需注意的是,poll是系统调用,当调用poll的时候,其实已经是陷入了内核,是内核线程在跑了。因此对于调 用poll的用户进程来讲,此时是阻塞的。
>
> 因为poll的底层实现,是去扫描每个文件描述符(fd),而如果要对感兴趣的fd进行扫描,那么只能将每个描述符设置成非阻塞的形式(对于用户进程来讲,设置 fd是阻塞还是非阻塞,可以使用系统调用fcntl),这样才有可能进行扫描。如果扫描当中,发现有可读(如果可读是用户感兴趣的)的fd,那么select就 在用户进程层面就会返回,并且告知用户进程哪些fd是可读的。


>
> > 这时候,用户进程仍然需要使用read的系统调用,将fd的数据,从内核缓冲区拷贝到用户进程缓冲区(这也是poll为同步IO的原因)。
>
> 那么此时的read是阻塞还是非阻塞呢?这就要看fd的状态了,如果fd被设置成了非阻塞,那么此时的read就是非阻塞的;如果fd被设置成了阻塞,那么此时 的read就是阻塞的。
>

> 不过程序已经执行到了这时候,不管fd是阻塞还是非阻塞,都没有任何区别,因为之前的poll,就是知道有数据准备好了才返回的,也就是说内核缓冲区已经有了数 据,此时进行read,是肯定能够将数据拷贝到用户进程缓冲区的。
>
> 但如果换种想法,如果poll是因为超时返回的,而我们又对一个fd(此fd是被poll轮询过的)进行read调用,那么此时是阻塞还是非阻塞,就非常有意义 了,对吧!


>
>
>
>
>
>
>
>
>
> > 结论
> > 判断IO是同步还是异步,是看谁主动将数据拷贝到用户进程。
> > select或者poll,epoll,是同步调用,进行此调用的用户进程也处于阻塞状态。
> > javaScript或者nodejs中的读取网络(文件)数据,然后提供回调函数进行处理,是异步IO。
>

> > fromhttp://blogread.cn/it/article.php?id=4108&f=sinat


>
> > --
> > jaywong
> > 已使用 Sparrow 发送
> > 已使用 Sparrow 发送
>
> > 在 2011年8月9日星期二,下午4:45,linux JHON 写道:
>
> >> 同步在进程和线程之间存在,也同样存在于IO。但是根据这里的上下文,应该问的是IO的同步。线程或进程的同步和互斥是另外一个话题了。
>
> >> 阻塞和非阻塞很好区别,所谓阻塞就是系统调用在IO调用完成时才返回,被阻塞的进程处于睡眠状态。
> >> 非阻塞IO是指不管系统调用是否完成都立刻返回,不会导致进程挂起。服务器的设计中都使用非阻塞IO,用于响应高并发的连接请求。
> >> 这里还有个概念就是IO复用,其实是阻塞到select或poll等这样的系统调用,而不是真正的read或write。
>
> >> 同步和异步IO:下面是POSIX的定义
> >> 所谓同步IO就是请求进程阻塞到直到IO操作完成时。阻塞IO和非阻塞IO都是同步IO。
> >> 异步IO就是IO操作不会引起请求进程的阻塞。
>
> >> 下面的话引自UNPv1
> >> 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.
>

Tomas Huang (冠)

unread,
Aug 17, 2011, 8:07:45 AM8/17/11
to pon...@googlegroups.com
我理解的也是如此。
nodejs中对于non-blocking主要描述也是针对于进程(结束||回收)....
--
Name: Tomas Huang(黄冠)
Nick: 青山老妖
Position: WEIMA SOFTWARE DESIGN CO.SHA Co-founder
Email: huanggua...@gmail.com
Sina Micro Bloghttp://t.sina.com.cn/showpower(青山老妖_黄冠)
Twitter: runawaygo
------
互联网创业者,理想主义者,敏捷实践,HTML5,软件工程师,非专业产品设计师

linux JHON

unread,
Aug 17, 2011, 8:31:24 AM8/17/11
to pon...@googlegroups.com
nodejs很流行吗?

Tomas Huang (冠)

unread,
Aug 17, 2011, 8:37:43 AM8/17/11
to pon...@googlegroups.com
简单好用,git上很火。
Reply all
Reply to author
Forward
0 new messages