异步开发相关概念
本系列博文用于记录FastAPI框架学习。
并发 vs 并行
在实际的开发中,我们一般关注的是并发而非并行,因为要实现真正的并行的话,必须有多核CPU或多个CPU支持,而硬件资源不管要多少都是有限的。而并发可以通过编程的方式轻松在一台电脑上实现成千上万的并发量。所以一般讨论网站的性能都是说网站的并发量是多少(一秒之内可以处理多少个请求),而不是并行怎么样。
并发(Concurrency)
并发是指在同一时间段内,有多个任务都在执行,但在任意时刻,只有一个任务在执行,即这些任务是交替执行的。例如,在多线程环境下,线程的切换是由操作系统来控制的,每个线程轮流获取CPU的执行时间,创建出并发执行的效果。并发可以在单核CPU上实现,也可以在多核CPU上实现。
并行(Parallelism)
并行是指在同一时刻,有多个任务同时在进行。例如,在多核CPU环境下,每个核心可以在同一时间运行一个任务,从而实现多个任务的并行处理。并行需要在多核(或者说多处理器)CPU上实现,因为在单核CPU上,任意时刻只能执行一个任务。
情景:给4只小鸭子喂食
为了更容易理解,这里使用给小鸭子喂食的例子来解释并发和并行的区别。假设你有一碗小鱼,需要喂给4只小鸭子(A, B, C, D)。
并发操作
现在只有你一个人饲养员,你的目标是让所有小鸭子都觉得自己在同时被喂食,但实际上你一次只能喂一只。
你给鸭子A喂了一勺食,但是小鸭子并不能立马吃完。在A吃食物的这个时间段,你转身给鸭子B喂食。鸭子B开始吃,你又转身去喂鸭子C……如此反复,在A、B、C、D之间快速循环。
在一个时间段内(比如1分钟),所有鸭子都吃到了食物(任务都在执行)。但在任何一个瞬间(比如百分之一秒),你只在喂其中一只鸭子(只有一个任务在执行)。
并发是逻辑上的同时发生。通过快速切换任务(喂食对象),模拟出“同时”的效果。
并行操作
现在,你和你的3个朋友,一共4个人
你开始给鸭子A喂食,在同一时刻,你的朋友也开始给鸭子B、C、D喂食。在同一个瞬间,4只鸭子同时吃到了食物(4个任务同时执行)。
并行是物理上的真正同时发生。它需要多个劳动力的支持。
对比
特性 | 并发 (Concurrency) | 并行 (Parallelism) |
---|---|---|
核心比喻 | 一个人,用一个勺子轮流快速喂四只鸭子。 | 四个人,同时各用一个勺子喂四只鸭子。 |
关键 | 任务切换 | 同时执行 |
目标 | 提高程序的响应能力和资源利用率,避免“干等”。 | 提高任务完成的总速度,缩短整体时间。 |
依赖 | 是一种程序设计和结构的方式。 | 依赖多核硬件支持。 |
简单来说:
- 并发是一个人同时 抛接多个球。
- 并行是多个人同时各自抛接一个球。
阻塞
阻塞是指在程序等待某个操作完成(通常指的就是/O操作)期间,自身无法继续执行的状态。在阻塞状态时,程序无法进行其他任务,只能等待,直到阻塞的操作完成。
非阻塞
非阻塞是指在程序执行某个操作时(通常指的就是/O操作),不需要等待该操作完成,可以继续执行其他任务。这样就可以提高程序的执行效率,避免因等待某个操作而浪费CPU的时间。
同步
同步是指在程序执行一个操作(如I/O操作)后,必须等待该操作完成后,才能继续执行下一步操作。这与阻塞有一定的相似性,但是,阻塞是指程序在等待某个操作(如I/O操作)完成的过程中自身无法继续执行,而同步只是要求操作按照某种预定的顺序一步一步地执行。同步不一定是阻塞
的。
异步
异步是指程序在执行一个操作(如I/O操作)后,不需要等待该操作完成,就可以继续执行其他操作。与非阻塞相比,非阻塞主要体现在单个操作上,当该操作无法立即得到结果时,不会阻塞程序的执行,而异步则是在程序设计层面,当一个异步过程启动后,程序可以在未得到结果时继续执行其他操作,异步过程在完成后,通过状态、通知和回调来通知主程序。