简单理解python异步编程与asyncio实现(一)

异步编程

在开始说明异步编程之前,首先先了解几个相关的概念。

阻塞

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

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

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

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

简单的理解的话,阻塞就是 A调用B,A会被挂起,一直等待B的结果,什么都不能干

非阻塞

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

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

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

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

简单理解的话,非阻塞就是 A调用B,A自己不用被挂起来等待B的结果,A可以去干其他的事情

同步

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

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

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

简单理解的话,同步就是A调用B,此时只有等B有了结果才返回

异步

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

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

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

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

简单理解的话,异步就是A调用B,B立即返回,无需等待。等B处理完之后再告诉A结果

并发

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

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

并行

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

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

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

总的来说,并行是为了利用多核加速多任务的完成;并发是为了让独立的子任务能够尽快完成;非阻塞是为了提高程序的整体运行效率,而异步是组织非阻塞任务的方式。

并发

是指的程序的组织结构,把程序设计成多个可以独立执行的子任务。目的是使用有限的计算机资源使得多个任务可以被实时或者接近实时执行为目的。

并行

指的是程序的执行状态,多个任务同时执行。这样做的目的是为了利用富余的计算资源(多核cpu),加速完成多个任务的目的。

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

综上

并行是为了利用多核计算机的富余计算资源来加速多任务程序完成的进度。

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

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

异步是组织非阻塞任务的方式。

异步编程

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

异步执行的程序一定是无序的,如果你可以根据已经执行的指令,准确的判断出,它接下里要去执行的某个具体操作,那么它就是同步程序。这是有序和无序的区别。

异步编程的困难在于,因为异步执行的程序,它的执行顺序不可预料,所以在并行情况下变得比较复杂和艰难。

所以几乎所有的异步框架都将异步编程模型简化:一次只允许处理一个事件。因此关于异步的讨论基本上都集中在了单线程中。

如果某个事件的处理过程过长,那么其他部分就会被阻塞。

所以异步编程的异步调度必须要“足够小”,不能耗时太久。

合理的用异步编程的方式可以提高 cpu 的利用率,提高程序效率。