并发和并行有什么区别?

1560

并发和并行有什么区别?


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

3

并发编程涉及那些似乎会重叠的操作,主要关注由于非确定性控制流导致的复杂性。与并发程序相关的数量成本通常是吞吐量和延迟。并发程序通常受到IO限制,但不总是如此,例如并发垃圾收集器完全在CPU上运行。并发程序的教学示例是网络爬虫。该程序启动对网页的请求,并同时接受下载结果作为响应,积累已经访问过的页面。控制流是非确定性的,因为每次运行程序时响应的顺序都可能不同。这种特点使得调试并发程序非常困难。一些应用程序从根本上来说就是并发的,例如Web服务器必须同时处理客户端连接。Erlang可能是最有前途的高度并发编程语言。
并行编程涉及那些为了提高吞吐量而重叠的操作。通过使控制流变得确定,避免了并发编程的困难。通常,程序会生成一组子任务并行运行,只有每个子任务都完成后,父任务才会继续执行。这使得并行程序易于调试。并行编程的难点是性能优化,包括粒度和通信等问题。后者在多核上下文中仍然是一个问题,因为将数据从一个缓存传输到另一个缓存需要相当大的成本。密集矩阵乘法是并行编程的教学示例,可以通过使用Straasen的分治算法并同时攻击子问题来高效地解决它。Cilk可能是在共享内存计算机(包括多核)上进行高性能并行编程的最有前途的语言。
从我的回答中复制: https://dev59.com/gXI-5IYBdhLWcg3wW2-p#3982782

3

这个来源给了我很好的解释:

并发(Concurrency)是指应用程序处理多个任务的方式。应用程序可以一个接一个地处理任务(串行),也可以同时处理多个任务(并行)。

而并行(Parallelism)则是指应用程序处理每个单独任务的方式。应用程序可以从头到尾依次处理任务,也可以将任务分成子任务并并行完成。

可以看出,应用程序可以是并发但不是并行的。这意味着它可以同时处理多个任务,但不会将任务拆分为子任务。

应用程序也可以是并行但不是并发的。这意味着应用程序一次只处理一个任务,而这个任务被拆分为可并行处理的子任务。

此外,应用程序既不是并发也不是并行的情况也存在。这意味着它一次只处理一个任务,且该任务永远不会被拆分为可并行执行的子任务。

最后,应用程序也可以同时具备并发和并行的特性,即它可以同时处理多个任务,并将每个任务拆分为子任务以实现并行处理。然而,在这种情况下,与单独使用并发或并行相比,一些并发和并行的优势可能会丧失,因为计算机中的CPU已经保持了合理的繁忙状态。同时使用可能只会带来小幅度的性能提升,甚至会导致性能下降。


这已经发布在这个现有的答案中。 - Pang

2

Pike对"并发(concurrency)"的理解是一种有意的设计和实现决策。一个具备并发能力的程序设计可能表现出行为上的"并行(parallelism)",这取决于运行环境。

你不希望一个没有为并发而设计的程序表现出并行性。:-) 但在相关因素(功耗、性能等)带来净收益的范围内,你希望采用最大并发设计,以便主机系统在可能的情况下可以并行执行。

Pike的Go编程语言极端地体现了这一点:他的函数都是可以正确并发运行的线程,即调用一个函数总是会创建一个线程,如果系统有能力,它将与调用者并行运行。在他的世界里,拥有数百甚至数千个线程的应用程序是再正常不过的事情了。(我不是 Go 专家,这只是我的看法。)


1

并发简单地意味着有多个任务在运行(不一定是并行的)。例如,假设我们有3个任务,则在任何时刻:可能有多个正在运行,或者全部同时运行。

并行意味着它们实际上是并行运行的。因此,在这种情况下,所有三个任务必须同时运行。


1
很好,让我举个例子来说明我的理解。 假设有三个孩子,分别叫做A、B、C。A和B在交谈,而C在听。 对于A和B,他们是并行的: A: 我是A。 B: 我是B。
但对于C来说,他的大脑必须进行并发处理以同时听A和B,可能会是这样的: 我是我 A 是 B。

1
我认为这个问题存在混淆,因为有两种不同的观点:程序员的观点(并发/并行编程)和计算机/操作系统的观点(并发/并行执行)。
计算机的观点在这里回答。
程序员的观点:
并发编程:程序员编写代码时知道该代码将由多个线程执行,原因可能是:在等待I/O时更好地利用CPU,通过不同的线程处理Web请求,在单独的线程中运行计算以使GUI响应,运行定期后台任务。程序员必须应用互斥构造、锁定/解锁、等待条件/信号、处理死锁等。多个线程可以在单个处理器/核心上运行(从计算机的角度看是并发),也可以在多个处理器/核心上运行(从计算机的角度看是并行)。

并行编程:程序员知道程序将在拥有多个处理器/核心的计算机上运行,并希望利用多个核心。程序员将一个 CPU 密集型的计算任务分成多个子任务,每个子任务在一个线程中运行,一旦线程完成,它们的结果就会被合并到总结果中(分而治之)。例如,将某些矩阵处理代码分解为并行处理矩阵部分的子任务。每个核心将执行一个线程来处理子任务(或者如果线程数大于核心数,则同时执行多个线程)。程序员必须在这里应用并发编程技术,但她也关注将任务分解为子任务并组合结果。例如,在 Java 中,程序员可以使用 ParallelStreams 自动拆分数据并组合结果。如果程序员知道程序将在单核处理器上执行,则将 CPU 密集型任务分解为多个线程是没有收益的。(摘自 Doug Leah 的《Java 并发编程:设计原则和模式,第二版,1999年,第343页)

并行程序专门设计用于利用多个 CPU 解决计算密集型问题。


0
仅为了给其他好的答案增加更多澄清:
基于这样一个前提,即处理的抽象(CPU作为一个相当可想象的例子)能够在同一时刻运行一个任务, 并发 是关于处理的抽象本身的故事:它可以在不同的任务之间切换。 并行 是关于我们拥有多个处理抽象(例如我们的CPU有多个核心)。所以这是我们系统能够同时执行几个任务的原因(字面上)。但是这里没有关于特定的处理抽象(它们是否并发)的任何说法。
这里的重点是这些故事关于什么
因此,在阅读接受的答案时要注意:
“并发”是指两个或更多任务可以在重叠的时间段内开始、运行和完成。
从严格意义上讲,根据该定义可以得出结论,即并行本身就预设了并发。

0

选自这篇博客的摘录:

并发和并行的区别:
并发是指两个任务可以在重叠的时间段内开始、运行和完成。并行是指任务实际上同时运行,例如在多核处理器上。
并发是独立执行进程的组合,而并行是(可能相关的)计算的同时执行。
并发是关于同时处理许多事情。并行是关于同时做许多事情。
一个应用程序可以是并发的 - 但不是并行的,这意味着它在同一时间处理多个任务,但没有两个任务在同一时间点执行。
一个应用程序可以是并行的 - 但不是并发的,这意味着它在多核CPU中同时处理一个任务的多个子任务。
一个应用程序既不是并行的 - 也不是并发的,这意味着它按顺序逐个处理所有任务。
一个应用程序既可以是并行的 - 也可以是并发的,这意味着它在多核CPU中同时并发处理多个任务。

一个应用程序可以是并行的,但不一定是并发的,这意味着它可以在多核CPU上同时处理一个任务的多个子任务。您能解释一下这句话吗?据我所知,一个并行应用程序总是并发的。 - Vaibhav Gupta

0

简单来说, 并发就是同时处理多个事情。

加粗的“处理”一词用于显示并发与并行之间的区别。同时处理多个事情意味着同时完成多个事情,但无论它们是否在同一时间执行都没有关系。另一方面,进行并行意味着同时执行许多事情(在同一时间执行)。因此,并发上下文可以使用一个或多个处理资源实现。使用一个处理资源同时处理多个事情意味着通过在任务之间进行上下文切换来同时完成许多事情。另一方面,具有多个处理资源的并发上下文意味着进行并行。这意味着我们通过并行实现并发,但反之不成立。

你可能想要了解更多关于并发和并行以及它们与现代技术的关系,请查看我的文章


0

并发是编程术语。它涉及多个任务在没有特定顺序的重叠时间段内开始运行和完成。并发由操作系统管理。当多个线程想要访问同一资源时,线程会出现竞争条件问题。此外,它们还会出现死锁,其中它们互相等待,防止自己运行。例如,您想在吃东西时说话。首先,您需要吞下嘴里的食物或停止咀嚼,然后才能说话(您正在切换线程),说完话后您可以再咬一口。

并行是硬件术语。它涉及多个任务在具有多个计算资源的硬件上实际同时运行,例如多核处理器。如果您能够在咀嚼食物时说话,这就是并行性。并行的一个例子是,一个人可以同时唱歌和跳舞。


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