异步编程和事件驱动

异步编程和事件驱动

一般我们学习的是传统的顺序编程, 所有发送给解释器的指令会一条条地被执行, 这样写出来的代码输出比较直观且可预测, 如果出了问题可以按照顺序执行下去即可发现问题, 可以比较好的开发和调试。

同步/异步

同步和异步描述的是进程/线程的调用方式

  1. 同步调用指的是线程发起调用后, 一直等待调用返回后才继续执行下一步操作, 这并不代表 CPU 在这段时间内也会一直等待, 操作系统多半会切换到另一个线程上去, 等到调用返回后再切换回原来的线程。

  2. 异步就相反, 发起调用后, 线程继续向下执行, 当调用返回后, 通过某种手段来通知调用者。

同步和异步中的调用返回指的是内核进程将数据复制到调用进程, 顺序编程里面通常调用是同步的, 上一步执行之后才会继续下一步。

现在我写了一个爬虫爬取一个网站, 为了提高抓取效率, 我会使用多线程和多进程编程, 假设由于网络或者对方网站等问题, 某段时间的请求对方响应很慢, 即使设置了超时时间, 在超时时间到来之前, 这些线程都是处于等待的状态。这时候我可以实现一个功能, 使得程序遇到这种情况的时候先跳过这一步, 执行下一个请求, 等执行完之后, 再执行这个请求, 如果还是没有响应, 那么切换到下下个请求, 这样就可以通过切换任务尽量减少闲置时间, 异步编程就是实现这样的功能的。

单线程的同步模型

假设现在有三个包含独立任务的程序。在同一时刻, 只能有一个任务在执行, 并且前一个任务执行结束后其他的任务才能开始。如果任务都能按照事先规定好的顺序执行, 最后一个任务的完成意味着所有任务都完成。

单线程的同步模型
单线程的同步模型

多线程/多进程的同步模型

在多线程/多进程的同步模型里面, 每个任务都在单独的线程(进程)中完成。

这些线程都是由操作系统管理的, 如果在多核 CPU 的系统里面, 它们可能会相互独立运行, 若在单处理器环境下, 则会交错运行。在线程模式中, 具体哪个线程执行, 是由操作系统决定的, 作为开发者, 只需要简单地认为它们的指令流是相互独立且可以并行执行的。多进程模式同理, 可以分配任务给对应的进程。

多线程和多进程编程较为麻烦的是线程或者进程之间的通信以及数据管理的问题。

多线程/多进程的同步模型
多线程/多进程的同步模型

异步编程模型

  1. 单线程。较多线程简单, 不需要担心操作系统收回任务的控制权, 因为决定权在开发者手中。

  2. 任务交错执行。开发者要做的就是将任务组织成一个序列来交替地小步完成, 每一个异步调用必须足够小, 不能耗时太久。

异步编程模型
异步编程模型

在上图不能明显体现出异步编程的优势, 而且任务的切换还会带来额外的开销。当任务强制等待或者阻塞的时候, 异步编程才能发挥优势, 如下图:

异步编程优势
异步编程优势

在上图中灰色部分代表这个时间段某个任务被阻塞, 阻塞的原因是等待 I/O 的完成(比如传输数据或者网络请求等等), 一个典型的 CPU 处理数据的能力是硬盘或者网络的几个数量级的倍数, 因此, 一个需要进行大的 I/O 操作的同步程序, 需要耗费大量的时间去等待硬盘或者网络将数据准备好, 正是因为这个原因, 同步的程序也叫阻塞程序。

阻塞/非阻塞

阻塞和非阻塞的概念是针对 IO 状态而言的, 关注的是程序在等待 IO 调用返回这段时间的状态。阻塞这个词来自操作系统的线程/进程的状态模型, 一个线程或者进程的执行会经历 创建 -> 就绪 -> 运行 -> 阻塞 -> 终止 5 个状态, 当线程需要某一个 IO 请求暂时得不到竞争资源时操作系统会把它阻塞起来避免浪费 CPU 资源, 等到有了资源再变成就绪的状态等待 CPU 的调度运行, 各个状态的转换如图所示:

线程状态
线程状态

阻塞和非阻塞, 以及同步和异步, 完全是两组概念, 它们之间并没有一个必然的联系。阻塞 != 同步, 非阻塞 != 异步。

I/O 编程模型

I/O 编程模型指操作系统在处理 IO 时所采用的方式, 这些模型是为了解决 I/O 速度问题而诞生的。UNIX 下的 I/O 编程模型主要有以下 5 种

  1. blocking I/O 阻塞 I/O。对于 I/O 来说, 通常分为两个阶段, 一个是准备数据, 一个是返回结果, 阻塞型 I/O 在进程发出一个系统调用请求之后, 进程就一直等待上述两个阶段完成, 等待拿到返回结果之后, 再重新运行。

  2. non-blocking I/O 非阻塞 I/O。和阻塞 I/O 比较类似, 不同之处时当进程发起一个调用后, 如果数据还没有就绪, 就会马上返回一个结果, 告诉进程现在还没有就绪, 和阻塞 I/O 的区别就在于用户进程会不断地查询内核状态, 这个过程依然是同步的。

  3. I/O multiplexing I/O 复用。I/O 复用是以轮询的方式来查询内核的执行状态, 它和非阻塞 I/O 的区别是一个进程可能会管理多个 I/O 的请求, 当某个 I/O 调用有了结果之后, 就返回对应的结果。

  4. signal driven I/O 信号驱动式 I/O

  5. asynchronous I/O 异步 I/O。当进程发出调用之后, 内核会立刻返回结果, 进程也会继续做其它事情, 直到操作系统返回数据之后, 会给用户进程发送一个信号。需要注意的是异步 I/O 并没有涉及任何关于回调函数的概念。

这 5 种模型中, 除了异步 I/O 之外, 其它的都是同步的。

异步模型具有优势的场景

  1. 有大量的任务, 因此在一个时刻至少有一个任务要运行。

  2. 任务执行大量的 I/O 操作, 这样同步模型就会在因为任务阻塞而浪费大量的时间。

  3. 任务之间相互独立, 以至于任务内部的交互很少。

这些条件大多是在 Client/Server 模式中的网络比较繁忙的服务器端出现, 比如 web 服务器, 每个任务代表一个客户端进行接收请求并回复的 I/O 操作, 客户端的请求相当于读操作, 它们是相互独立的, 因此, 网络服务是异步模型的典型代表。

事件驱动模型

事件驱动模型主要应用在图形用户界面(GUI)、网络服务和 Web 前端上。比如编写图形用户界面程序, 要给界面上每个按钮都添加监听函数, 而该函数只有在相应的按钮被用户点击的事件发生时才会执行, 开发者并不需要事先确定事件何时发生, 只需要编写事件的响应函数即可。监听函数或者响应函数就是所谓的事件处理器(event handler), 类似的事件还有鼠标移动、按下、松开、双击等等, 这就是事件驱动。

事件驱动的程序一般都有一个主循环(main loop)或称事件循环(event loop), 该循环不停地做两件事: 事件监测和事件处理。首先要监测是否发生了事件, 如果有事件发生则调用相应的事件处理程序, 处理完毕再继续监测新事件。事件循环只是在一个进程中运行的单个线程。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容