彻底理解:阻塞、非阻塞、同步、异步、Reactor、Proactor

原创 2016年06月01日 20:06:37
我以前是写AS3的,事件和回调无处不在,天生就是异步的,很少需要讨论这些概念。现在写C#,这些概念提的就多了,所以需要彻底搞明白。如果把技术的逻辑抽象出来,跟生活中的逻辑做比较,你会发现技术包含的道理是多么的朴素呀。

本程序中的代码大部分是示意代码,不能真正运行。

1、阻塞:阻塞是指当前线程被堵住了,不能继续往下执行了,就被操作系统挂起了。

阻塞的对象是当前线程,而不是IO被阻塞了;外部资源(通常是IO)使得当前线程被挂起才叫阻塞,内部程序执行的再慢也不叫阻塞,比如一个JPEG.Encode(),虽然这个函数的执行很慢,但它仍然在执行,不叫阻塞。阻塞的核心表现是等待,什么事情都做不了,只有等待。

2、非阻塞:调用外部资源,不管结果如何,不会阻挡线程的继续执行。

3、同步:“调用”然后得到“结果”。可能立即得到结果,可能等待一毫秒,也可能等待一辈子,反正结果必须紧随其后。

同步的概念关键在于结果必须紧随调用者之后到来,可以有等待,也可以没有等待,不管有没有等待,同步跟阻塞都没有必然关系。比如同步非阻塞接口Socket.NoBlockRecv(),一旦调用它,有数据就返回数据,没数据就返回空数据或错误,反正不会让你等待。

还有一个同步非阻塞的例子是协程,协程是一种巧妙的机制,既实现了同步返回结果(不像Socket.NoBlockRecv()没有数据就返回空数据或错误当结果),又不会阻塞当前线程。下面是Unity3D的协程的例子:

   IEnumerator WaitAndDebug()
    {
          //打印一句日志
        Debug.Log("WaitAndDebug start" + Time.time);
        //这句的执行要花费5秒,但5秒时间段内,当前线程可以干其它事,同步非阻塞。
        yield return new WaitForSeconds(5);
        //5秒后再打印一句日志
        Debug.Log("WaitAndDebug done" + Time.time);
    }

4、异步:“调用”,有“结果”再通知我。异步跟同步的区别是,结果返回时间点跟调用发起时间点没有强制关系,调用者是被动得到结果的,不是主动等待结果的。

5、Reactor:响应模式,我是被动的,外部要我干什么,我就干什么,受外部驱动。Reactor模式虽然起源于网络IO设计,但这种思想是通用的。基于Reactor模式的网络IO是这样的:

首先声明要监听哪些事件
socket.addEventHandler("receiveEvent",  receiveHandler);
socket.addEventHandler("canSendEvent",  canSendHandler);

function receiveHandler()
{
     socket.receive();//IO告诉我有数据来了,我才去接收数据,同步的
}

function canSendHandler()
{
     socket.send();//IO告诉我它不繁忙了,可以发送数据了,我才去发数据,同步的
}

Reactor的核心是被动响应,程序响应IO事件,具体的收发操作还是需要程序自己去完成,虽然这期间没有阻塞,但收发操作还是同步的。

6、Proactor:主动模式,我是主动的,我想什么时候干,就什么时候干,不受外部驱动。基于Proactor模式的网络IO是这样的:

socket.addEventHandler("receiveSuccessEvent",  receiveSuccessHandler);
socket.addEventHandler("sendSuccessEvent", sendSuccessHandler);

//不用关心IO是否繁忙,发就是了,成功了会通知我的,通过sendSuccessEvent事件
socket.sendAsync(data);
//不用关心有没有数据,我想何时接收就接收,如果我不执行接收,就永远不会触发receiveSuccessEvent事件
socket.receiveAsync();

function receiveSuccessHandler(data)
{
    log("received data");//IO已经把数据接收好了,然后通知我,异步的
}

function sendSuccessHandler()
{
     log("send data success");//IO把数据发送成功了,然后通知我,异步的
}

举个形象的例子:去银行取款。
Reactor:拿号,某个柜台空闲了就通知我去取款,我还是必须坐到柜台前取款,取款过程还是同步的。
Proactor:拿号,告诉大堂经理我要取款,款到了,大唐经理送到我手中,取款过程是异步的。

以上都是个人理解,如果有错误的地方,欢迎大家指正。



reactor和proactor模式

首先分享一下,我在网上看到的两篇不错的文章:正是这两篇文章才理解了reactor和proactor模式;  Reactor模式,或者叫反应器模式 高性能IO设计的Reactor和Proacto...
  • caiwenfeng_for_23
  • caiwenfeng_for_23
  • 2013年01月02日 08:11
  • 26200

两种高效的服务器设计模型:Reactor和Proactor模型

I/O模型 在文章《unix网络编程》(12)五种I/O模型中提到了五种I/O模型,其中前四种:阻塞模型、非阻塞模型、信号驱动模型、I/O复用模型都是同步模型;还有一种是异步模型。 Reactor...
  • u013074465
  • u013074465
  • 2015年05月30日 18:25
  • 6587

Reactor和Proactor的区别

1.先解释同步和异步: 同步异步是一种通信机制。 同步:调用方需要保持等待直到I/O操作完成。 异步:调用方可以不用保持等待,只需要操作系统完成I/O操作通知调用方就可以了。 2.再说说阻塞和...
  • zhuziyu1157817544
  • zhuziyu1157817544
  • 2017年05月17日 14:42
  • 223

Boost.Asio学习之Proactor模式简介

Boost.asio学习之Proactor模式简介
  • zhangxiao93
  • zhangxiao93
  • 2017年01月05日 15:58
  • 504

Java网络编程(四) Reactor和Proactor模式

http://zhaohuiopensource.iteye.com/blog/1517730 在高性能的I/O设计中,有两个比较著名的模式Reactor和Proactor模式,其中Reactor模...
  • ckchenwei
  • ckchenwei
  • 2016年07月03日 12:02
  • 743

Reactor与Proactor的区别

1、标准定义 两种I/O多路复用模式:Reactor和Proactor 一般地,I/O多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)。分离器对象可将来自事...
  • windows_nt
  • windows_nt
  • 2014年05月06日 17:42
  • 4057

两种高性能I/O设计模式(Reactor/Proactor)的比较

综述 这篇文章探讨并比较两种用于TCP服务器的高性能设计模式。 除了介绍现有的解决方案,还提出了一种更具伸缩性,只需要维护一份代码并且跨平台的解决方案(含代码示例),以及其在不同平台上的微调。 此文还...
  • shixin_0125
  • shixin_0125
  • 2017年12月21日 00:20
  • 138

socket阻塞与非阻塞,同步与异步、I/O模型

socket阻塞与非阻塞,同步与异步 作者:huangguisu 1. 概念理解      在进行网络编程时,我们常常见到同步(Sync)/异步(Async),阻塞(Block)/非...
  • hguisu
  • hguisu
  • 2012年04月12日 16:35
  • 195769

IO - 同步,异步,阻塞,非阻塞 (亡羊补牢篇)

当你发现自己最受欢迎的一篇blog其实大错特错时,这绝对不是一件让人愉悦的事。 《 IO - 同步,异步,阻塞,非阻塞 》是我在开始学习epoll和libevent的时候写的,主要的思路来自于文中...
  • historyasamirror
  • historyasamirror
  • 2010年07月31日 12:51
  • 137087

IO 的阻塞和非阻塞二:轮询操作

介绍驱动中 IO 的非阻塞的 poll/select
  • qqliyunpeng
  • qqliyunpeng
  • 2016年09月06日 11:08
  • 1132
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:彻底理解:阻塞、非阻塞、同步、异步、Reactor、Proactor
举报原因:
原因补充:

(最多只允许输入30个字)