并发和并行有什么区别?

1560

并发和并行有什么区别?


347
并发是两排顾客从同一个收银员处点单(排队轮流点单);并行是两排顾客从两个收银员处点单(每一排都有自己的收银员)。 - chharvey
13
我认为这应该是答案。简洁明了(如果去掉“简短回答”的话只有两行文字),直接表达,易于理解。做得好! - Mike Maxwell
4
记忆这个比喻的助记符:并发 == 同时的“顾客”;并行 == 同时的“支付”。 - chadoh
2
@chharvey的简短回答很好。我想再加一句话来更清楚地解释:“在这里,每个收银员代表您机器的一个处理核心,而顾客则是程序指令。” - Code True
2
我不明白为什么@chharvey的答案会被投票这么多次 - 它是错误的。并发是指同时发生的事情的概念。并行是实现这一点的一种机制(同时进行计算)。如果我依次进行多个API请求,然后等待它们完成,这是并发但不是并行。 - Guy
显示剩余8条评论
41个回答

40

简单例子:

并发是:"两个队列访问一个ATM机"

并行是:"两个队列和两个ATM机"


多线程呢?我在想多线程这个术语如何适用于上述情况。在这种情况下,Concurrent是否等同于Multithreading,即每个时刻ATM机从每个队列中各取一个? - KhoPhi
1
@KhoPhi 多线程意味着并发,但不意味着并行。如果我错了,请有人纠正我。 - bool3max
@KhoPhi 多线程,顾名思义,基本上是将一个应用程序分成多个线程,在单个CPU核心上并发运行(即它们的执行是交错的)。bool3max,这也是我的理解,如果没有通过多核多线程的硬件支持,无法实现并行执行。 - uzluisf

35

它们解决不同的问题。并发性解决了CPU资源稀缺和任务众多的问题。因此,您可以通过代码创建线程或独立的执行路径,以便在稀缺资源上共享时间。直到最近,并发性一直占据讨论的主导地位,因为CPU可用性。

并行性解决了找到足够任务和适当任务(可以正确分割的任务)并在丰富的CPU资源上分配它们的问题。当然,并行性一直存在,但由于多核处理器如此便宜,它正在走向前沿。


33

并发: 多个执行流同时运行,可能共享资源。

例: 两个线程竞争 I/O 端口。

并行: 将问题分解为多个相似的部分进行处理。

例: 通过在文件的每一半上运行两个进程来解析大文件。


17

并发 => 当多个任务在共享资源的情况下,可能会最大化资源利用率,在重叠时间段内同时执行。

并行 => 将单个任务分解为多个简单独立的子任务,可以同时执行。


你如何描述一个单核处理器系统,它通过多任务(时间片)来呈现重叠处理的外观?当并发被定义为在重叠时间段内执行时,它包括这种处理。你已经描述了同时执行,这在你对并发的定义下是不包括的。 - acarlon
在我看来,这是最好的定义,但你应该将“共享资源”改为“共享可变资源”。 - Philippe

14

那个表格本可以被更清晰但同样错误的说法所取代:“并发等同于异步,而并行等同于多线程”。 - Bananach

11
如果你想向一个9岁的孩子解释这个问题。

enter image description here


10

把它想象成服务队列,服务器只能服务于队列中的第一个任务。

1个服务器,1个作业队列(有5个作业)->没有并发性,也没有并行性(只有一个作业被完整地服务,队列中的下一个作业必须等待已处理的作业完成,并且没有其他服务器可以为其提供服务)

1个服务器,2个或更多不同的队列(每个队列都有5个作业)->并发性(因为服务器与所有队列中的第一个作业共享时间,平等或加权),但仍然没有并行性,因为在任何时刻,只有一个作业正在被服务。

2个或多个服务器,一个队列->并行性(同时完成2项作业),但没有并发性(服务器不共享时间,第三项作业必须等到其中一个服务器完成才能开始执行)

2个或多个服务器,2个或多个不同的队列->并发性和并行性

换句话说,并发性是共享时间来完成作业,可能需要相同的时间来完成作业,但至少可以早些开始。重要的是,作业可以被分成较小的作业,这允许交错。

仅通过更多的CPU、服务器、人员等运行并行程序即可实现并行性。

请记住,如果资源是共享的,则无法实现纯粹的并行性,但这就是并发性具有最佳实际用途的地方,它可以处理不需要该资源的另一个作业。


我认为即使只有一个队列,这个解释也是错误的:调度程序仍然可以中断Process1并将其放回队列,给Process2一些时间等等,以便它看起来像P1和P2是同时运行的,即并发运行。 - Harry

9

我非常喜欢保罗·布切尔(Paul Butcher)对这个问题的答案(他是《七周七并发模型》一书的作者):

虽然并行和并发经常被混淆,但它们是不同的东西。并发是问题域的一个方面——你的代码需要处理多个同时(或几乎同时)发生的事件相比之下,并行是解决方案领域的一个方面——你想通过并行处理问题的不同部分来使程序运行更快。一些方法适用于并发,一些适用于并行,还有一些同时适用于两者。了解你所面临的问题并选择正确的工具来完成工作。


8

来自 Robert Love 的书籍《Linux 系统编程》:

并发、并行和竞态

线程创建了两个相关但不同的现象:并发和并行。这两者都是双刃剑,涉及到线程的成本以及它的好处。并发是两个或多个线程在重叠的时间段内执行的能力。并行是同时执行两个或多个线程的能力。并发可以在没有并行的情况下发生,例如在单处理器系统上进行多任务处理。并行(有时强调为真正的并行)是一种特定形式的并发,需要多个处理器(或者具有多个执行引擎的单个处理器,例如 GPU)。在并发中,多个线程推进,但不一定是同时的。而在并行中,线程确实是并行执行的,允许多线程程序利用多个处理器。

并发是一种编程模式,一种解决问题的方法。并行是硬件特性,通过并发可实现。两者都是有用的。

这个解释与所接受的答案一致。实际上,这些概念比我们想象的要简单得多。不要将它们看作是魔法。并发是关于一段时间的,而并行则是关于同时并且具有同时性


7
我将提供一个与一些流行答案略有冲突的答案。在我看来,并发是一个通用术语,包括并行。并发适用于任何情况下,不同的任务或工作单元在时间上重叠。并行更具体地适用于评估/执行不同工作单元在同一物理时间的情况。并行的存在意义是加速可以从多个物理计算资源中受益的软件。适合并发的另一个主要概念是交互性。当任务的重叠可从外部世界观察时,交互性适用。 交互性的存在意义是制作对真实世界实体(如用户、网络对等方、硬件外围设备等)响应的软件。
并行和交互几乎完全独立于并发维度。对于特定项目,开发人员可能关心其中任何一个,两者或都不关心。它们往往会被混淆,尤其是因为线程这种令人憎恶的东西提供了一个相当方便的原语来同时处理两者。
关于并行的更多细节: 并行存在于非常小的尺度上(例如,处理器中的指令级并行),中等尺度上(例如,多核处理器)和大尺度上(例如,高性能计算集群)。由于多核处理器的增长,对软件开发人员公开更多线程级并发的压力在最近几年有所增加。并行与依赖关系的概念密切相关。依赖关系限制了可以实现的并行程度;如果一个任务依赖另一个任务,则两个任务不能并行执行(忽略推测)。
程序员使用许多模式和框架来表达并行性:管道、任务池、数据结构上的聚合操作(“并行数组”)等。
关于交互性的更多细节: 实现交互的最基本和常见方法是使用事件(即事件循环和处理程序/回调)。对于简单的任务,事件很好用。试图使用事件执行更复杂的任务会涉及堆栈撕裂(也称为回调地狱;也称为控制反转)。当您对事件感到厌倦时,可以尝试更奇特的东西,如生成器、协程(也称为Async/Await)或协作线程。
出于对可靠软件的热爱,请不要在交互性方面使用线程。
对罗布·派克的“并发不是并行;它更好”的口号我不喜欢。并发既不比并行好也不比并行差。并发包括交互,无法用更好/更差的方式与并行进行比较。这就像说“控制流比数据更好”。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接