[Javascript] 并发与并行
今天我们来解决一个很多同学经常搞混的概念对:并发和并行。
这两个词在日常交流中常常被混用,但在编程领域,它们指的是完全不同的执行模式。理解它们的区别,不仅能帮你正确选型,还能在调优性能时少走弯路。
一个小问题
👉 一边刷手机一边等外卖,这算是并发还是并行?
如果你下意识觉得“反正就是同时干两件事”,那这篇文章你一定要看完。我会用简单直观的比喻让你彻底搞清这两个概念,并且和 JS 中的典型特性相关联。
并发(Concurrency)
定义:在同一时间段内,多个任务交替进行。
这些任务没有真正同时运行,而是通过 任务切换 来营造“同时进行”的效果。
- 类比:一个服务员同时负责 3 桌客人,他会先给 A 桌上菜,再去 B 桌点单,然后回到 C 桌加水……看起来像是同时照顾三桌,其实是快速切换任务。
- 特点:一个执行单元(单线程)通过任务切换处理多个任务。
并行(Parallelism)
定义:在同一时刻,多个任务真正同时运行。
通常依赖于 多核 CPU 或 多台机器 的并行执行。
- 类比:3 个服务员分别负责 3 桌客人,大家同时干活,互不干扰,这就是真正的同时进行。
- 特点:需要多个执行单元(多线程、多进程、多核硬件)共同工作。
并发 vs 并行对比
维度 | 并发(Concurrency) | 并行(Parallelism) |
---|---|---|
定义 | 多个任务在同一时间段交替执行 | 多个任务在同一时刻真正同时执行 |
实现方式 | 单线程任务切换、事件循环、调度器 | 多线程、多进程、多核 CPU 同时执行 |
硬件依赖 | 无需多核,可在单核 CPU 上实现 | 通常需要多核 CPU 或多台机器 |
类比 | 一个服务员轮流服务多桌客人 | 多个服务员同时服务多桌客人 |
优势 | 节省资源,实现简单 | 性能强,适合 CPU 密集型任务 |
劣势 | CPU 密集任务下切换开销大 | 实现复杂,线程/进程通信开销大 |
JS 中的并发
JavaScript 是一门 单线程语言,同一时刻只有一个任务在运行。
那遇到耗时长的任务怎么办?
👉 如果原地等待,整个页面就会“卡死”,用户无法进行任何操作。
因此,JS 通过 事件循环(Event Loop) 和 异步回调机制 来实现并发:
- 定时器(
setTimeout
/setInterval
) - 异步 IO(如
fetch
、XMLHttpRequest
) - Promise / async-await
这些都属于并发机制:即任务并没有真正同时执行,而是交替调度。
JS 中的并行
前面已经解释了并行的概念。JS 作为一门单线程语言,本身是不能直接并行执行代码的,
但它可以借助额外的线程来实现并行,比如:
- 浏览器环境:Web Worker
- Node.js 环境:Worker Threads
这类 API 的本质,是通过在后台开启新的线程去运行代码,从而让多个计算任务真正同时进行,
并且通过消息机制与主线程通信。
⚠️ 注意:无论是 Web Worker 还是 Worker Threads,涉及的细节非常多,随便哪一个单独拎出来都能写成新的系列文章。这里只需要理解它们是实现并行的手段即可。