vlambda博客
学习文章列表

异步编程相关概念浅析

云深之无迹
纵是相见,亦如不见,潇湘泪雨,执念何苦
381篇原创内容
Official Account
https://mp.weixin.qq.com/s?__biz=MzIxMjY5NTE0MA==&mid=2247483720&idx=1&sn=f016c06ddd17765fd50b705fed64429c
https://www.jianshu.com/p/c4dc7866eb81
http://cs.brown.edu/courses/cs196-5/f12/handouts/async.pdf

异步编程相关概念浅析

异步编程相关概念浅析

这篇是一个英文的资料

先给出很好的文章,上文自取


首先知道,什么是阻塞:

  • 程序未得到所需计算资源时被挂起的状态。

  • 程序在等待某个操作完成期间,自身无法继续干别的事情,则称该程序在该操作上是阻塞的。

了解何为同步:

  • 不同程序单元为了完成某个任务,在执行过程中需靠某种通信方式以协调一致,称这些程序单元是同步执行的。

  • 例如购物系统中更新商品库存,需要用“行锁”作为通信信号,让不同的更新请求强制排队顺序执行,那更新库存的操作是同步的。

  • 简言之,同步意味着有序

什么是异步:

  • 为完成某个任务,不同程序单元之间过程中无需通信协调,也能完成任务的方式。

  • 不相关的程序单元之间可以是异步的。

  • 例如,爬虫下载网页。调度程序调用下载程序后,即可调度其他任务,而无需与该下载任务保持通信以协调行为。不同网页的下载、保存等操作都是无关的,也无需相互通知协调。这些异步操作的完成时刻并不确定。

  • 简言之,异步意味着无序

什么是并发:

  • 并发描述的是程序的组织结构。指程序要被设计成多个可独立执行的子任务。

  • 以利用有限的计算机资源使多个任务可以被实时或近实时执行为目的。


什么是并行:

  • 并行描述的是程序的执行状态。指多个任务同时被执行。

  • 以利用富余计算资源(多核CPU)加速完成多个任务为目的。


最后总结:

  • 并行是为了利用多核加速多任务完成的进度

  • 并发是为了让独立的子任务都有机会被尽快执行,但不一定能加速整体进度

  • 非阻塞是为了提高程序整体执行效率

  • 异步是高效地组织非阻塞任务的方式




通过图解形式,我们假设 一个程序包含了概念上不同的三个任务,当然这三个任务可以完成我们的程序。注意我并没有使用技术性相关的,需要特别处理的任务。

第一种模型是单线程同步模型,其如下图所示:

异步编程相关概念浅析

图1 单线程同步模型

这是最简单的编程模型,每个任务按照时间的顺序一个接一个的依次执行。如果所有的任务都是按照定义的顺序执行的,后续的任务在实现的过程中,可以假设前面的任务执行的过程中没有出现错误,而且他们所有的输出都是可以直接拿来使用的。

在图2中,我们比较了单线程同步模型和多线程模型(线程模型)。在多线程模型中,每一个任务由一个独立的线程控制。这些线程由操作系统管理,在一个多处理器或多核的环境中,真正的并发执行,也可能在一个单处理器中交替的执行。关键是,在线程模型种,程序执行的细节由操作系统操作,程序员可能简单的认为指令流是同时执行的。尽管例图很简单,但实际上多线程编程会变得很复杂,因为线程之间在执行的过程中需要相互同步。线程通信和同步是一个高级的编程话题,掌握它可能有些困难。

异步编程相关概念浅析

图2 多线程模型

一些程序使用多个进程实现并行性,而不是多个线程。虽然编程细节不同,在概念上是相同的模型,如图2所示

现在我们可以介绍异步模型了,如图3描述的那样:

图3异步模型

在异步模型中,各个任务是相互交错的,由一个单线程控制。这要比多线程模型简单,因为程序员知道,当一个任务执行时,另一个任务不会被被执行。虽然在一个单核处理器的系统中,一个多线程的程序也是一种交错的模式,但程序员在思考时应该像图2那样,而不是图3,避免程序移植到多处理器的系统中发生错误。但在单线程异步模型中,无论是在单处理器还是多处理器中,都是交错的执行的。

异步编程模型和多线程模型还有另外一个不同点。在多线程系统中,推迟一个任务的执行而去执行另一个任务大大的超出了程序员的控制。尽管,这个在操作系统的控制下,但程序员只能猜测一个任务被推迟,另一个任务来替代,可能在任何可能的时候发生。相比较,在异步模型中,一个任务会继续执行除非显示的放弃控制权给另一个任务。

2 动机

在一些方面,异步模型比多线程模型要简单,因为异步模型有简单的指令流,而且显示的让出控制权,而不是像多线程一样被随意的暂停。但是异步模型有它自己的复杂性,程序员必须组织每一个任务作为一系列的交替执行的小的步骤。如果一个任务使用了另一个任务的输出,那么所依赖的任务接收该任务的输入作为一连串的比特或块而不是所有的放在一起。

由于并没有实际的并行性,正如我们的图解所示,一个异步的程序可以和一个长时间执行的同步程序一样。在这样的一个条件下,一个异步的程序可以表现得比一个同步的程序更好,有时候也相反。这个条件就是我们的任务被强制的等待或阻塞,就如图4所示:

图4中断的同步程序

在图3中,灰色的部分代表一个任务被阻塞不能进行任何的步骤。为什么一个任务会被阻塞?一个频率较高的原因是它在等待I/O,从一个外部的设备传输数据。


和一个同步的程序相比,一个异步的程序在以下的情况中表现得更好:

1.存在大量的任务,大多数时间至少有一个任务在执行

2.任务执行大量的I/O操作,导致一个同步的程序浪费大量的时间在阻塞当其他的任务可以执行时

3.任务之间是相互独立的,各个任务很少需要内部的交流(因为一个任务等待另一个任务)