请解释 什么是 并发和并行 它们有什么区别

接入与开发

用生活化例子讲清并发与并行的区别,帮初学者搞懂这两个词在写代码和调接口时到底指什么、什么时候用哪个。

写代码时总看到「并发」和「并行」两个词,文档里混着用,翻译过来又差不多,于是很多人默认它们是一回事。结果一到设并发数、算线程池、看接口限流的时候就开始犯迷糊。这篇不讲术语定义,就用排队打饭、食堂窗口这类场景,把两者的差别、关系和各自适用的情况说明白,最后给一套自己动手验证的小步骤。

写代码时总看到「并发」和「并行」两个词,文档里混着用,翻译过来又差不多,于是很多人默认它们是一回事。结果一到设并发数、算线程池、看接口限流的时候就开始犯迷糊:到底该加机器,还是该加请求数?这两个词背后对应的是完全不同的判断方向。

这篇不讲术语定义,就用排队打饭、食堂窗口这类场景,把两者的差别、关系和各自适用的情况说明白。读完之后你至少能做到一件事:看到一段代码或一个接口描述,能判断它说的是「任务怎么排」还是「任务怎么跑」,然后决定该调哪个旋钮。

为什么这两个词老是被搞混

最容易踩的坑是中文翻译。concurrency 和 parallelism 翻过来都带「同时」两个字,字面上完全看不出差别,但英文原词的语义侧重其实不一样:一个讲任务调度的交错,一个讲同一时刻真的一起跑。很多教程和产品文档自己都没分清,读者自然跟着糊。

想把混淆解开,不用先背定义,先把「谁在同时」拆成两个独立的问题:第一,任务之间有没有交错执行的痕迹;第二,执行单元有没有多个。这两个问题各有答案,四个组合一摆出来,概念自己就分开了。

任务交错
同一段时间内多个任务都在推进,但推进的瞬间是错开的
执行单元
真正干活的载体,比如 CPU 核、线程、进程、机器
调度
决定哪个任务此刻能拿到执行单元的那套规则
  • 中文翻译太像:都是「同时做几件事」,字面上看不出差别
  • 英文原词一个讲任务调度交错,一个讲同一时刻真的一起跑
  • 很多文档和教程混用,导致读者以为是一回事
  • 先把「谁在同时」拆成两个问题,混淆就散了

并发:一个人同时应付好几件事

想象你一个人坐在工位上,三个电话同时打进来。你不可能同时说三句话,只能接起一个、说两句、让对方稍等,再切到第二个。十分钟下来三件事都推进了一点,但任意一个瞬间你只在跟一个人讲话。这就是并发的核心画面:任务之间有交错,执行的人只有一个。

落到代码上,单核 CPU 上跑多任务、单线程事件循环、协程切换,都是这个路子。操作系统或运行时按时间片轮转,做出「大家都在动」的错觉。判断标准很简单:把执行过程打上时间戳,能看到任务 A、任务 B、任务 A 这样交替出现的痕迹。

观察点并发场景下的表现
执行单元数量通常只有一个在真正干活
任务推进方式你一段我一段,交替推进
速度提升来源把等待的时间利用起来,不是靠人多
典型代码形态事件循环、协程、async 任务调度

什么情况下这个理解不适用:多核机器上你照样可以只写并发逻辑,只是底层运行时可能顺手把任务分到不同核上,看起来像并行了。所以「并发」描述的是你写代码时怎么组织任务,不是硬件层面到底几个核在转。

并行:几个人各干一件事,真的一起干

换一个场景:食堂中午排队,只开一个窗口,队伍排到门口;后来开了三个窗口,三个人同时打饭,队伍很快消化掉。这里的关键不是「切换得快」,而是同一时刻真的有三个人在分别干活。这才是并行。

代码里的并行,靠的是增加执行单元:多核 CPU 上开多进程、GPU 上多卡分摊、多台机器一起算。判据也很直接:同一时刻有多个执行单元在跑,速度提升来自「人多」。但前提是活能拆开——如果任务之间有强依赖,硬拆反而更慢,因为同步和通信的开销会吃掉收益。

  1. 先确认任务能不能拆把任务画成依赖图,看有没有可以独立跑的片段。全是串行依赖的链条,加人也没用。
  2. 再确认执行单元够不够看机器有几个核、能不能多开进程。单核上谈并行,基本是空谈。
  3. 最后量收益加执行单元前后各测一次总耗时,如果提升远小于投入,说明瓶颈不在算力,而在别处。

两者的关系:并行是并发的一种结果

这两个词不是并列关系,而是层次不一样。并发讲的是「任务怎么组织、怎么被调度」,并行讲的是「任务怎么被执行」。你可以只用并发调度,却不真正并行;但反过来,几乎不存在完全不并发的并行,因为总得有个东西负责把任务分派下去。

组合情况是否可能说明
并发但不并行常见单核跑多任务,靠切换推进
既并发又并行常见多核上既调度又真正同时执行
并行但不并发几乎不存在分派任务本身就需要调度行为
既不并发也不并行常见老老实实串行执行

还有一种容易忽略的情况:你在本机写的并发代码,部署到多核机器上跑,运行时可能自动把任务摊到多个核,表现上就带上了并行的效果。所以判断的时候要看两层:你写的逻辑是什么结构,底层实际拿到了几个执行单元。

代码里怎么一眼看出来是哪一种

看代码不用逐行读,抓两个特征就够:任务是靠「让出执行权」推进的,还是靠「增加执行单元」推进的。前者的关键词是事件循环、协程、async;后者的关键词是线程池、多进程、多卡、多机分摊。

更实用的一个判断角度是看瓶颈在「等」还是在「算」。大量等网络、等磁盘的场景,并发收益最大,因为你把原本干等的时间填满了;纯计算、CPU 一直跑满的场景,才需要并行来真正提高吞吐。搞反了就会出现「加了一堆并发,结果更慢」的情况。

  • 看关键词:事件循环、协程、async 偏向并发;线程池、多进程、多卡、多机偏向并行
  • 看瓶颈:等 IO 为主去想并发,算力打满去想并行
  • 看失败现象:加并发数没变快,多半瓶颈在 CPU;加机器没变快,多半瓶颈在依赖或锁
  • 拿不准就先量一把基线,别凭感觉拍数字

如果手上有接口,可以先测出延迟和耗时基线,再决定往哪个方向调。站内 /tools/speed-test 可以先跑一遍,拿到你自己的数字再对照着看,比看别人的结论靠谱。

搞清区别对实际开发有什么用

最直接的一个影响是设并发数。并发数是「同时挂多少个请求在服务端」,不是「用几个核」。很多人按本机核数去拍这个值,结果要么压垮下游,要么浪费了等待时间。这是两个完全不同的旋钮,转错了方向自然没效果。

第二个影响是本地和线上的差异。本地跑得快不代表线上快:单机并行受核数限制,接口侧还受服务端限流限制。你在本地压出来的数字,到线上可能完全对不上,因为限制条件换了。

你面对的场景该往哪个方向想常见误区
接口调用慢,但 CPU 很闲并发方向:让等待时间重叠起来直接去加机器
纯计算任务,CPU 长期打满并行方向:增加真正的执行单元疯狂加大并发数
加了并发反而更慢瓶颈在锁、依赖或下游限流以为是并发数还不够
加了机器没变化任务本身拆不开或强依赖以为是机器不够多

如果对术语边界还没把握,可以先到站内 /ai-dict/category/tech 把相关词条对齐一遍,再去看具体场景,会顺很多。涉及到各家模型的并发上限和限流规则,数值会变,别记死数,到站内价格与模型资料相关页面核对当时的数字。

动手验证:三步分清你手上的场景

概念讲完了,关键是你能不能对自己手上的活儿做出判断。下面这套三步走,不依赖任何工具,拿纸笔或者开个文档就能做完,做完之后你对当前场景的定位会清楚很多。

  1. 第一步,写下任务类型把任务归成三类:等网络、等磁盘、纯计算。分类依据是这段时间里执行单元到底在忙还是在闲。三类分完,方向基本就定了。
  2. 第二步,观察执行痕迹给任务打上开始和结束时间戳,看是交替推进(A 一段 B 一段 A 又一段),还是同一时刻多路一起推进。前者偏并发,后者偏并行。
  3. 第三步,改一个变量看结果只动一个变量:加大并发数,看总耗时变不变;或者加机器核数,看总耗时变不变。哪个有效,就说明瓶颈在哪一边。一次只动一个,不然分不清是谁的功劳。

验证过程中建议把结论随手记下来,记清楚任务类型、瓶颈位置、动哪个变量有效。下次遇到排期和容量估算,直接翻记录复用,比重新推一遍省事。要对比不同服务侧的限制条件,可以到站内中转站与价格追踪相关页面看当时的数据。

并发是让等待时间被填满,并行是让计算时间被摊薄。想清楚你在省哪种时间,旋钮就不会转错。
下一步如果你正准备给接口调并发数,先去跑一遍延迟基线,再回来对照上面那张表判断瓶颈在哪边。

常见问题

并发是不是一定比串行快?

不一定。如果任务是纯计算且只有一个执行单元,并发只是来回切换,还多了切换开销,可能更慢。并发真正能提速的场景是任务大量在等外部资源,比如等接口返回、等磁盘读写,这时候让别的任务先跑才有意义。判断前先看瓶颈在哪。

单核 CPU 上能有并行吗?

严格意义上同一时刻只有一个执行单元在算,做不到真正的并行。但单核上完全可以写出并发的程序,靠快速切换让多个任务看起来都在推进。如果你需要的是实打实的同一时刻多路执行,就得看有没有多个核或多个执行单元。

多线程就等于并行吗?

不等于。线程只是一种组织方式,多个线程是不是真的同时跑,取决于底层有没有多个可用的执行单元、以及运行时怎么调度。语言和框架里的线程模型差别很大,用之前建议先确认它的调度方式,别默认写了线程就是并行。

为什么加了并发数反而更慢、还报错?

常见原因是把并发当成了免费的加速手段。任务之间争抢同一份资源、或者对端有速率限制时,并发数越高冲突越多。这时候应该先降并发、加退避,再逐步抬高找拐点。限流相关的排查思路在站内已有专门文章,这里不重复。

这个概念跟调 API 有什么关系?

关系很直接。你设的并发数决定同一时刻挂多少个请求出去,直接影响会不会被限流、以及账单涨多快。具体单价和额度折算按各家官方口径,去站内 /official-api 看当时的数字,别拿旧截图当依据。

本文依据各平台公开文档与官方公告整理,只做中文归纳;具体做法、参数与限制以官方文档为准。