并发和并行之间的区别是什么?


当前回答

我喜欢Rob Pike的演讲:并发不是并行(这更好!)(幻灯片)(谈话)

Rob通常谈论Go,并且通常以直观直观的解释来解决并发与并行的问题!下面是一个简短的总结:

任务:让我们烧掉一堆过时的语言手册!一次一个!

并发:任务有许多并发分解!一个例子:

并行性:如果至少有2个地鼠同时工作或不工作,则前面的配置会并行出现。

其他回答

在电子学中,串行和并行表示一种静态拓扑,决定电路的实际行为。当没有并发时,并行性是确定性的。

为了描述动态的、与时间相关的现象,我们使用了术语顺序和并发。例如,可以通过特定的任务序列(例如配方)获得特定的结果。当我们与某人交谈时,我们会产生一系列单词。然而,在现实中,许多其他过程在同一时刻发生,因此,与某一行动的实际结果一致。如果很多人在同一时间谈话,同时进行的谈话可能会干扰我们的顺序,但这种干扰的结果事先不知道。并发性引入了不确定性。

串行/并行和顺序/并行表征是正交的。数字通信就是一个例子。在串行适配器中,数字消息沿同一通信线路(例如,一根电线)临时(即顺序)分布。在并行适配器中,这也在并行通信线路(例如多条电线)上进行划分,然后在接收端进行重构。

让我们想象一个有9个孩子的游戏。如果我们将它们作为一条链处理,在开始时发送消息,在结束时接收消息,我们将进行串行通信。更多的单词组成了一系列的交流单元。

I like ice-cream so much. > X > X > X > X > X > X > X > X > X > ....

这是在串行基础结构上复制的顺序过程。

现在,让我们想象一下,把孩子们分成三组。我们把这个短语分成三部分,第一部分给左边的孩子,第二部分给中心线的孩子,等等。

I like ice-cream so much. > I like    > X > X > X > .... > ....
                          > ice-cream > X > X > X > ....
                          > so much   > X > X > X > ....

这是一个在并行基础结构上复制的顺序过程(尽管仍部分序列化)。

在这两种情况下,假设孩子之间有完美的沟通,结果会提前确定。

如果有其他人与您同时与第一个孩子交谈,那么我们将同时进行处理。我们不知道基础设施将考虑哪个过程,因此最终结果尚未提前确定。

并发:如果一个处理器解决了两个或多个问题。

并行性:如果一个问题由多个处理器解决。

在我看来,理解这两者最简单、最优雅的方式是这样的。并发允许交错执行,因此会产生并行的错觉。例如,这意味着并发系统可以在您用Word编写文档的同时运行Youtube视频。底层操作系统是一个并发系统,使这些任务能够交错执行。由于计算机执行指令的速度如此之快,这就给人一种同时做两件事的感觉。

平行性是指这样的事情实际上是平行的。在上面的示例中,您可能会发现视频处理代码在一个内核上执行,而Word应用程序在另一个内核中运行。注意,这意味着并发程序也可以并行!使用线程和进程构建应用程序,使程序能够利用底层硬件,并可能并行完成。

那为什么不让一切都平行呢?一个原因是因为并发是一种结构化程序的方式,是一种促进关注点分离的设计决策,而并行常常以性能的名义使用。另一个问题是,有些事情根本上无法完全并行完成。这方面的一个例子是在队列的后面添加两件事——不能同时插入这两件事。一定要有东西在前面,另一个在后面,否则你会把队伍弄得一团糟。虽然我们可以交错这种执行(因此我们得到了一个并发队列),但不能让它并行。

希望这有帮助!

我认为在这个问题上有两种不同的观点导致了混淆:程序员的观点(并发/并行编程)与计算机/操作系统的观点(并行/并行执行)。

这里回答了计算机的观点。

程序员的观点:

并发编程:程序员编写代码时知道代码将由多个线程执行,无论出于何种原因。原因可能是:在等待I/O时更好地利用CPU,通过不同线程处理Web请求,通过在独立于主线程的线程中运行计算,运行周期性后台任务,使GUI做出响应。程序员必须应用互斥构造、锁定/解锁、等待条件/信号、处理死锁等。多个线程可以在单个处理器/内核上运行(从计算机的角度来看是并发的),也可以在多个内核上运行。

并行编程:程序员知道程序将在具有多个处理器/内核的计算机上运行,并希望利用多个内核。程序员将CPU密集型计算划分为多个子任务,在一个线程中运行每个子任务,一旦线程完成,其结果将合并为总结果(分而治之)。例如,将一些矩阵处理代码划分为并行处理矩阵部分的任务。每个核心将使用子任务执行一个线程(如果线程数大于内核数,则同时执行多个线程)。程序员也必须在这里应用并发的编程构造,但她也关注将任务划分为子任务并合并结果。例如,在Java中,程序员可以使用ParallelStreams来分割数据并自动合并结果。如果程序员知道程序将在单核处理器上执行,那么将CPU密集型任务拆分为多个线程是没有好处的。摘自Doug Leah的《Java并发编程:设计原则和模式》,1999年第2版,第343页:

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

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

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