并发、并行和异步方法有什么区别?

335

并发指的是两个任务在不同线程上同时运行。而异步方法在同一个线程上并行运行。这是如何实现的?并行又是什么呢?

这3个概念有什么区别?


19
“异步”这个术语可能有很多不同的含义。这些术语是相关的,但它们并不描述互不相交的事物集合。这些含义有重叠,并根据情况而异。 - Pointy
2
首先,并发性是指同时运行两个或更多进程。但与此同时,并发并不等同于并行。并行进程需要两个或更多核心,而并发进程可以共享单个核心的时间。 - Rick O'Shea
这是一个近乎重复的问题,类似于 https://dev59.com/t3NA5IYBdhLWcg3wNa-T,那里也有一些很好的答案。不同之处在于这个问题询问异步方法的区别,而另一个问题则未涉及。 - Maxpm
17个回答

241

"并发"和"并行"原则实际上是相同的,正如您正确推测的那样,两者都涉及任务同时执行,但我认为"并行"任务应该是真正的多任务,即在「同一时间」执行,而"并发"可能意味着这些任务共享执行线程,但仍然看起来是在并行执行。

"异步方法"与前面两个概念没有直接关系,异步性用于呈现并发或并行任务的印象,但实际上,异步方法调用通常用于需要远离当前应用程序进行工作的进程,我们不希望等待并阻塞应用程序等待响应。

例如,从数据库获取数据可能需要时间,但我们不希望阻塞用户界面等待数据。异步调用使用回调引用,并在请求已经传递给远程系统后立即将执行返回到您的代码。您的用户界面可以继续响应用户,而远程系统则可以执行所需的任何处理。一旦它返回数据到回调方法,那么该方法就可以根据需要更新用户界面(或交付该更新)。

从用户的角度来看,它看起来像是多任务处理,但实际上可能不是。


编辑:

值得注意的是,在许多实现中,异步方法调用将导致线程启动,但这并非必要,这实际上取决于正在执行的操作以及响应如何通知回系统。


77
我认为你在第一段中混淆了并行性和并发性。并发性是指管理多个执行线程,而并行性更具体地指同时执行多个执行线程。并发性是一个更广泛的术语,可以包含并行性。 - Mark H
11
虽然这两个词非常相似,容易混淆(并且经常被混淆),但它们有不同的定义:Concurrent = 同时存在、发生或完成。Parallel = 指多个操作在同一时间内,由同一个或不同的设备表现或实际执行。可以看出,Parallel并不一定意味着Concurrent,只是表面上看起来是同时进行的。总之,这两个词通常可以互换使用,如果有n个开发人员在一间房里,你可能会得到n+1个定义;) - Lazarus
6
如果您打算根据市场营销材料中单词的用法来定义词典中的词语,那么我认为您可能会处于某种劣势。 - Lazarus
22
在编程的上下文中,"concurrency" 指的是你的代码能够被“组合”成可以同时运行的逻辑块的能力。而结合 "concurrency" 的 "parallelism" 则是将这些代码在一台 100 核心的计算机上运行。 - Frank Radocaj
6
@FrankRadocaj是正确的。并发意味着程序可以被分成单元(这些单元本质上是线程),可以以任何顺序运行,并且具有确定的结果。并行意味着这些单元/线程在多个处理器上实际上同时运行。 - user7917402
显示剩余6条评论

174

并发是指多个任务的执行交替进行,而不是每个任务按顺序依次执行。

并行是指这些任务实际上是在同时执行的。

enter image description here


{{异步}}是一个单独的概念(尽管在某些情况下相关)。它指的是一个事件可能与另一个事件发生的时间不同(不同步)。下面的图表说明了同步和异步执行之间的区别,其中演员可以对应于不同的线程、进程甚至服务器。

enter image description here

enter image description here


23
简单而有效的插图。 - contactmatt
1
并发与异步是一样的吗? - nos
2
这两个概念非常接近,但并不相同。在实践中,异步更多地涉及操作之间的交互(比如A和B),其中一个操作(B)由另一个操作(A)触发,并且第二个操作是否会等待第一个操作完成。并发是一个更一般的术语,用于描述可以彼此无关的操作,无论它们是按顺序执行还是交错执行。 - Dimos
3
异步通常涉及阻塞和非阻塞。 - Daniel
9
你对并发的定义是错误的。并发既不意味着非并行也不意味着并行,它只是指能够把程序分成多个部分并任意重新排序,以便每个部分都可以由单独的线程运行,但这并不意味着运行是否并行。并发是处理“许多事情同时进行”的能力,而并行是处理“同时进行许多事情”的能力。 “__并发_允许_并行”__:维基百科 - aderchox
显示剩余2条评论

60

并发可以在以下几种情况下发生:

异步 — 这意味着您的程序执行非阻塞操作。例如,它可以通过HTTP启动对远程资源的请求,然后继续执行其他任务,同时等待接收到响应。这有点像发送电子邮件后,在等待响应时继续自己的生活。

并行 — 这意味着您的程序利用多核计算机的硬件,通过将工作分解为任务,并在不同的核心上执行每个任务,来同时执行任务。这有点像在淋浴时唱歌:您实际上正在完全相同的时间内做两件事。

多线程 — 这是一种软件实现,允许不同的线程同时执行。即使在单核计算机上运行,多线程程序看起来也像在同时进行几件事情。这有点像通过不同的即时通讯窗口与不同的人聊天;虽然您实际上在不断地切换,但最终结果是您在同时进行多个对话。


4
这些比喻非常好!谢谢。可以说并发可以用多线程的定义来解释吗?因此,并发=在单核心上的多线程,看起来像是同时发生,但实际上是快速地来回切换? - wongz

28
并发意味着同时执行多个任务,但不一定是同时进行。当您需要执行多个任务但只有一个资源时,我们采用并发。在单核环境中,通过上下文切换实现并发。
并行是指同时执行多个任务,就像您可以同时唱歌和洗澡一样。现在您正在并行执行任务。
异步这个术语与线程执行有关。在异步模型中,当一个任务被执行时,您可以切换到另一个任务,而无需等待前一个任务完成。
异步编程帮助我们实现并发。在多线程环境中,异步编程是实现并行性的一种方式。

24

每个人都很难将异步与并行或并发关联起来,因为异步不是并行或并发的反义词,它是同步的反义词。这只是指如果某些东西(在本例中是线程)将与其他东西(在本例中是另一个线程)同步。


12

我会简洁有趣地介绍这些概念。

并发 vs. 并行 - 任务执行的方式。

举个现实生活中的例子:有一个挑战要求你既要吃完一整个大蛋糕,又要唱一首完整的歌曲。如果你是最快的完成了唱歌和吃蛋糕,你就能赢得比赛。所以规则是你要同时(concurrently)唱歌和吃蛋糕。具体怎么做不属于规则范畴。你可以先把整个蛋糕吃掉再唱整首歌,或者你可以先吃半个蛋糕再唱半首歌,然后重复上述步骤,等等。

并行是并发的一种特殊形式,其中任务真正同时执行。在计算机科学中,只有在多核环境下才能实现并行。

同步 vs. 异步 - 编程模型。

在同步(synchronous)中,你编写的代码是按照从上到下的顺序依次执行的步骤。在异步编程模型中,你编写的代码是作为任务被执行的,并行执行这些任务。并发执行意味着所有任务可能同时执行。


10

4
"Medium不是信息来源,而是某人谈论他(误)解某个主题的文章,这并不使他/她成为权威。" - Moha the almighty camel
6
这是一份引用文献,因此需要注明出处。这里的大多数答案都不是由任何领域的权威人士撰写的,作者提供的解释已经足够好了。 - Pedro Boechat
在stackoverflow上,至少有一个投票系统,并且这是一个由专业人士组成的社区。任何人都可以在medium上写任何东西。这两者之间并不是公平的比较。 - Moha the almighty camel
4
在这里,任何人都可以写任何东西,我不知道你为什么针对Medium。无论如何,我是一名专业程序员,我支持这种理解。我认为它很优雅,因为它相对来说比较简短。 - Pedro Boechat
问题不在于 Medium 是一个糟糕的来源,问题在于仅仅链接到外部页面的答案不是一个真正的答案。 如果您详细阐述引用部分或总结文章内容而不只是链接,那么您可以大大改善这个答案。 - David Schwartz
1
我认为我的错误在于假设它是不言自明的。 - Pedro Boechat

8

并发性

并发性意味着应用程序同时(并行)处理多个任务。如果计算机只有一个CPU,则该应用程序可能无法确切地同时处理多个任务,但是应用程序内部会同时处理多个任务。在开始下一个任务之前,它不会完全完成一个任务。

并行性

并行性意味着应用程序将其任务分成较小的子任务,可以在多个CPU上同时处理。

详细比较并发性和并行性

如您所见,并发性与应用程序处理多个任务的方式有关。应用程序可以按顺序处理一个任务(串行),也可以同时处理多个任务(并行)。

另一方面,并行性与应用程序处理每个单独任务的方式有关。应用程序可以从头到尾按顺序处理任务,也可以将任务拆分为子任务,这些子任务可以并行完成。

如您所见,应用程序可以是并发的,但不是并行的。这意味着它可以同时处理多个任务,但任务没有被拆分为子任务。

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

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

最后,应用程序可以同时具有并发性和并行性,即它同时处理多个任务,并将每个任务拆分为可并行执行的子任务。但是,在这种情况下,可能会失去并发性和并行性的某些优势,因为计算机中的CPU已经通过并发性或并行性保持相当繁忙。组合可能只导致小的性能提升甚至性能下降。在盲目采用并发并行模型之前,请务必进行分析和测量。

摘自http://tutorials.jenkov.com/java-concurrency/concurrency-vs-parallelism.html


6
并行:它是一个广义的术语,意味着两个代码片段"同时"执行。无论它是"真正"的并行还是通过一些巧妙的设计模式来伪造,都不重要。关键是你可以在同一时间启动“任务”,然后分别控制它们(使用互斥锁和所有适当的技巧)。
但通常情况下,人们更喜欢将“并行”一词仅用于“真正”的并行处理,例如:你通过非合作式多任务处理(无论是通过CPU/GPU核心,还是仅在软件级别上由操作系统在非常低的级别管理)使其发生。人们不愿意仅对伪造并行处理的复杂顺序代码(例如在浏览器窗口的javascript中找到的代码)说“并行”。这就是为什么本主题中的人们说“异步与并行无关”的原因。它确实与之有关,但请勿混淆它们。 并发:没有并行处理就不可能有并发处理(无论是模拟还是真正的,并如我上面所解释的),但这个术语专注于两个系统将尝试同时访问同一资源的事实。它强调了你将要处理这个问题。 异步:每个人都是正确的,异步与并行处理无关,但它为之铺平了道路(使事情并行化或不并行化的负担在于你——请继续阅读)。
"异步"指的是并行处理的一种表示形式,它正式化了通常涉及并行处理的三个基本要素:1)定义任务的初始化(例如何时开始和获取哪些参数),2)完成任务后必须执行的操作,以及3)代码在其中执行的内容。
但它仍然只是语法(通常表示为回调方法)。在幕后,底层系统可能只是决定这些所谓的“任务”只是堆积起来的代码片段,直到它完成当前正在执行的代码。然后它一个接一个地依次执行它们。或者不这样做。它也可以为每个任务创建一个线程并并行运行它们。谁在乎呢?这部分不包含在概念中 ;)

6
用比喻解释这些术语。
你的房子需要洗碗和洗衣服。
并发:你不需要等待一个任务完成再开始执行另一个任务。例如,你可以先开始洗碗,或同时开始洗碗和洗衣服。它们可以以任何顺序完成,即使你先开始洗碗,也可能先洗完衣服。
并行:在房子里有多个人做事;例如,你可以洗碗,另一个人可以洗衣服。
异步:你让某个人去洗衣服,又让某个人去洗碗。他们可以是同一个人(即你让他们去洗衣服,然后立即告诉他们去洗碗)。他们完成每个任务后会向你报告。
同步:你要求某个人去洗碗。你等待他完成。当他完成后,你可以做别的事情(你可以让他下一步去洗衣服,或自己去洗,或者做其他事情;关键是你要等待第一个任务完成,你与他保持同步)。

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