本文翻译自http://tutorials.jenkov.com/java-concurrency/concurrency-vs-parallelism.html,机翻加人工校正,仅供学习交流。
并发与并行
并发和并行通常用于多线程程序。乍一看,并发性和并行性似乎是指相同的概念,然而,并发和并行实际上有不同的含义。在这个并发与并行的教程中,我将解释这些概念的含义。
事先说明,在本文中,我将讨论单个应用程序(单个进程)中的并发性和并行性,不在多个应用程序、过程或计算机之间。
并行vs并行教程视频
如果你更喜欢视频,我这里有一个视频版本的教程:并行vs并行教程视频
并发
并发性意味着应用程序在多个任务上同时,或者至少表面上是同时运行。
如果计算机只有一个CPU,应用程序不能同时运行多个任务,但是应用程序中的进程同时是有多个任务的。为了同时在多个任务上取得进展,CPU在执行过程中在不同的任务之间切换。如下图所示
并行
并行执行是指一台计算机有多个CPU或CPU核心,同时在多个任务上取得进展。然而,并行执行并不是指与并行性相同的现象。稍后我将回到并行性。并行执行如下所示:
并行并发执行
线程分布在多个CPU中,并行并行执行是可能的。因此,线程在同一个CPU上执行是并发执行的,而在不同cpu上执行的线程是并行执行的。下图演示了并行并发执行。
并行性
并行性这个术语意味着应用程序将其任务分成更小的可以并行处理的子任务,比如同时在多个CPU上运行。因此,即使它们在表面上看起来很相似,并行性并不是指与“并行并发执行”相同的执行模型。
要实现真正的并行,你的应用程序必须有多个线程在运行,每个线程必须在单独的CPU / CPU内核/显卡GPU内核或类似的内核上运行。
下图展示了一个更大的任务,它被分成了4个子任务。这4个子任务由4个不同的线程执行,运行在2个不同的cpu上,这意味着,这些子任务的部分是并发执行的(那些在同一个CPU上执行的),和部分是并行执行(那些执行在不同的cpu上)。
如果4个子任务由4个线程执行,每个线程运行在各自的CPU上(总共4个CPU),然后任务的执行将是完全并行的。然而,将一个任务分解成与CPU数量一样多的子任务并不总是容易的。通常,把一个任务分解成几个子任务更容易,这些子任务与接下来的任务自然匹配,然后让线程调度器负责在可用的CPU之间分配线程。
并发和并行组合
简要概括,并发性就是在一个CPU上几乎同时处理多个任务(又名并发)。
另一方面,并行性与应用程序如何并行执行单个任务有关,通常是将任务划分为可以并行完成的子任务。
这两种执行风格可以在同一个应用程序中组合,下面我将介绍其中一些组合。
并发,不并行
应用程序可以是并发的,但不能是并行的,这意味着它似乎同时(并发地)在多个任务上取得进展。但是应用程序在每个任务的进展之间切换直到任务完成。在并行线程/ CPU中没有真正的任务并行执行。
并行,不并发
应用程序也可以是并行的,但不是并发的。这意味着应用程序一次只处理一个任务,这个任务被分解成可以并行处理的子任务.但是,在拆分并并行执行下一个任务之前,每个任务(子任务)都要完成。
既非并行也非并行
此外,应用程序也可以既不能并发也不能并行,这意味着它一次只处理一个任务,并且这个任务永远不会被分解成子任务。这可能是小型命令行应用程序的情况,它只有一个作业,这个作业太小了,无法并行化。
并发和并行
最后,一个应用程序也可以通过两种方式同时实现并发和并行:
第一个是简单的并行并发执行,如果应用程序启动多个线程,然后在多个CPU上执行,就会发生这种情况。
第二种方法是应用程序同时处理多个任务,并将每个任务分解为并行执行的子任务。然而,在这个场景中,并发性和并行性的一些好处可能会丢失,因为计算机中的CPU已经相当忙碌地处理并发性或并行性。将它们组合在一起可能只会带来很小的性能提高,甚至是性能损失。确保在盲目地采用并行模型之前进行分析和度量。