彻底理解:阻塞、非阻塞、同步、异步、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的区别

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

reactor和proactor模式

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

关于Reactor和Proactor的区别

系统I/O 可分为阻塞型, 非阻塞同步型以及非阻塞异步型。 阻塞型I/O意味着控制权只到调用操作结束了才会回到调用者手里。 非阻塞同步是会立即返回控制权给调用者的。调用者不需要等等,它从调用的函...

reactor/proactor模型简介

Reactor和preactor都是IO多路复用模式,一般地,I/O多路复用机制都依赖于一个事件多路分离器(Event Demultiplexer)。分离器对象可将来自事件源的I/O事件分离出来,并分...

Unity3D之协程(Coroutines & Yield )

写游戏代码,往往最终需要代码为连续的事件.结果会像这样: [它可以实现将一段程序延迟执行或者将其各个部分分布在一个时间段内连续执行。] private int state = 0; void ...
  • jjiss318
  • jjiss318
  • 2012年04月10日 22:29
  • 62173

Unity中Socket和多线程导致Editor和程序卡住解决

Editor卡住的原因Unity中使用Socket或者多线程,资源没有正确的释放导致Editor卡住。我们的项目中卡住是由于线程没有正确的关掉,TcpClient没有Close导致的。避免Socket...

Unity协程和线程的区别

先简要说下结论: 协同程序(coroutine)与多线程情况下的线程比较类似:有自己的堆栈,自己的局部变量,有自己的指令指针(IP,instruction pointer),但与其它协同程序共享全局变...

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

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

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

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

【高并发编程】再谈同步、异步、阻塞、非阻塞

同步、异步、阻塞、非阻塞的概念一直是计算机学科中很重要的概念,而这种细微的差别常常被大家混淆,我自己在过一段时间后也需要复习。今天再次翻出这个概念,仍然觉得不够清晰,今天再次深入了解了这四大天王。 以...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:彻底理解:阻塞、非阻塞、同步、异步、Reactor、Proactor
举报原因:
原因补充:

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