文章内容

2019/10/16 15:45:13,作 者: 黄兵

python 异步概念

1 什么是异步编程

通过学习相关概念,我们逐步解释异步编程是什么。

1.1 阻塞

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

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

  • 常见的阻塞形式有:网络I/O阻塞、磁盘I/O阻塞、用户输入阻塞等。

阻塞是无处不在的,包括CPU切换上下文时,所有的进程都无法真正干事情,它们也会被阻塞。(如果是多核CPU则正在执行上下文切换操作的核不可被利用。)

1.2 非阻塞

  • 程序在等待某操作过程中,自身不被阻塞,可以继续运行干别的事情,则称该程序在该操作上是非阻塞的。

  • 非阻塞并不是在任何程序级别、任何情况下都可以存在的。

  • 仅当程序封装的级别可以囊括独立的子程序单元时,它才可能存在非阻塞状态。

非阻塞的存在是因为阻塞存在,正因为某个操作阻塞导致的耗时与效率低下,我们才要把它变成非阻塞的。

1.3 同步

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

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

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

1.4 异步

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

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

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

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

上文提到的“通信方式”通常是指异步和并发编程提供的同步原语,如信号量、锁、同步队列等等。我们需知道,虽然这些通信方式是为了让多个程序在一定条件下同步执行,但正因为是异步的存在,才需要这些通信方式。如果所有程序都是按序执行,其本身就是同步的,又何需这些同步信号呢?

1.5 并发

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

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

1.6 并行

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

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

并发提供了一种程序组织结构方式,让问题的解决方案可以并行执行,但并行执行不是必须的。

1.7 概念总结

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

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

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

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

要支持并发,必须拆分为多任务,不同任务相对而言才有阻塞/非阻塞、同步/异步。所以,并发、异步、非阻塞三个词总是如影随形。

1.8 异步编程

  • 以进程、线程、协程、函数/方法作为执行任务程序的基本单位,结合回调、事件循环、信号量等机制,以提高程序整体执行效率和并发能力的编程方式。

如果在某程序的运行时,能根据已经执行的指令准确判断它接下来要进行哪个具体操作,那它是同步程序,反之则为异步程序。(无序与有序的区别)

同步/异步、阻塞/非阻塞并非水火不容,要看讨论的程序所处的封装级别。例如购物程序在处理多个用户的浏览请求可以是异步的,而更新库存时必须是同步的。

1.9 异步之难(nán)

  • 控制不住“计几”写的程序,因为其执行顺序不可预料,当下正要发生什么事件不可预料。在并行情况下更为复杂和艰难。

所以,几乎所有的异步框架都将异步编程模型简化一次只允许处理一个事件。故而有关异步的讨论几乎都集中在了单线程内。

  • 如果某事件处理程序需要长时间执行,所有其他部分都会被阻塞。

所以,一旦采取异步编程,每个异步调用必须“足够小”,不能耗时太久。如何拆分异步任务成了难题。

  • 程序下一步行为往往依赖上一步执行结果,如何知晓上次异步调用已完成并获取结果?

  • 回调(Callback)成了必然选择。那又需要面临“回调地狱”的折磨。

  • 同步代码改为异步代码,必然破坏代码结构。

  • 解决问题的逻辑也要转变,不再是一条路走到黑,需要精心安排异步任务。

分享到:

发表评论

评论列表

user-ico

追梦互联 on 回复 有用(0

追梦互联:http://idc.wywgw.xyz 追梦两天:http://bbs.wywgw.xyz