关于语言不可知:并发和并行有什么区别?

What is the difference between concurrency and parallelism?

并发和并行有什么区别?

请举例说明。


并发性是指两个或多个任务可以在重叠的时间段内启动、运行和完成。这不一定意味着他们两个都会同时运行。例如,在单核机器上进行多任务处理。

并行性是指任务同时运行,例如在多核处理器上。

引用Sun的多线程编程指南:

  • 并发性:至少有两个线程正在进行的情况。一种更通用的并行形式,可以将时间切片作为虚拟并行的一种形式。

  • 并行性:当至少两个线程同时执行时出现的情况。


为什么会有混乱

由于这两个词的字典含义几乎相同,因此存在混淆:好的。

  • 并发:同时存在、发生或完成(dictionary.com)
  • 平行:非常相似,经常同时发生(梅里亚姆韦伯斯特)。

然而,它们在计算机科学和编程中的使用方式却截然不同。以下是我的解释:好的。

  • 并发性:可中断性
  • 并行性:独立性

那么我所说的上述定义是什么意思呢?好的。

我将用现实世界中的类比来澄清。假设你必须在一天内完成两项非常重要的任务:好的。

  • 领取护照
  • 完成演示文稿
  • 现在,问题是任务1要求你去一个非常官僚的政府办公室,让你排队等4个小时才能拿到护照。同时,任务2是您办公室的一项重要任务。两者都必须在特定日期完成。好的。案例1:顺序执行

    通常情况下,你会开车到护照办公室2个小时,排队等候4个小时,完成任务,开车回去2个小时,回家,再保持清醒5个小时,完成演示。好的。案例二:同时执行

    但你很聪明。你提前计划好了。你随身携带一台笔记本电脑,在排队等候的时候,你就开始准备你的演讲了。这样,一旦你回到家,你只需要多工作1个小时而不是5个小时。好的。

    在这种情况下,这两个任务都是由您完成的,只是部分地完成。您在排队等候时中断了Passport任务,并进行了演示。当您的号码被调用时,您中断了演示任务并切换到Passport任务。由于这两个任务的可中断性,节省时间基本上是可能的。好的。

    并发性IMO可以理解为ACID中的"隔离"属性。如果子事务可以以任何交错方式执行,并且最终结果与两个任务按顺序完成时的结果相同,则认为两个数据库事务是孤立的。记住,对于护照和演示任务,您是唯一的执行者。好的。案例3:并行执行

    现在,既然你是个聪明人,你显然是个更高层次的人,而且你有一个助手。所以,在开始护照任务之前,你给他打电话,告诉他准备演示文稿的初稿。你花了一整天的时间完成护照任务,回来看看你的邮件,然后找到演示稿。他已经做了一个相当可靠的工作,并且在两个多小时内进行了一些编辑,你就完成了。好的。

    现在,因为你的助理和你一样聪明,他可以独立完成这项工作,而不需要经常要求你澄清。因此,由于任务的独立性,它们由两个不同的执行者同时执行。好的。

    还有我吗?好吧…好的。案例4:同时但不平行

    还记得你的护照任务吗,你要在哪排队等候?因为这是你的护照,你的助理不能排队等你。因此,Passport任务具有可中断性(您可以在排队等候时停止它,并在稍后调用您的号码时恢复它),但不具有独立性(您的助手不能代替您等待)。好的。案例5:平行但不同时

    假设政府办公室有一个安全检查进入该房屋。在这里,您必须移除所有电子设备并将其提交给军官,并且只有在您完成任务后,他们才会返回您的设备。好的。

    在这种情况下,护照任务既不是独立的,也不是可中断的。即使你在排队等候,你也不能在别的地方工作,因为你没有必要的设备。好的。

    同样地,假设这个陈述在本质上是高度数学化的,你需要100%的集中至少5个小时。即使你随身带着笔记本电脑,你也不能在排队等候护照任务时这样做。好的。

    在这种情况下,演示任务是独立的(您或您的助手可以投入5个小时的集中精力),但不能中断。好的。案例6:并行执行

    现在,假设除了指派你的助理参加演示外,你还随身携带一台笔记本电脑来完成护照任务。当您排队等候时,您会看到您的助手已经在共享平台中创建了前10张幻灯片。你对他的工作发表评论,并加以修正。稍后,当你回到家,而不是2小时完成草案,你只需要15分钟。好的。

    这是可能的,因为表示任务具有独立性(你们中的任何一个都可以做到)和中断性(你们可以停止它,稍后再继续)。因此,您同时执行这两个任务,并并行执行表示任务。好的。

    我们可以说,除了过于官僚主义,政府办公室还是腐败的。这样,你就可以显示你的身份,输入它,开始排队等候你的电话号码,贿赂一个警卫和其他人来保持你的位置,溜出去,在你的电话号码被呼叫之前回来,然后继续等待你自己。好的。

    在这种情况下,您可以同时和并行地执行Passport和演示任务。你可以溜出去,你的职位由你的助理担任。然后你们两个都可以做演讲,等等。好的。回到计算机科学

    在计算领域,以下是每种情况的典型示例场景:好的。

    • 情况1:中断处理。
    • 案例2:当只有一个处理器,但由于I/O,所有执行的任务都有等待时间时。
    • 案例3:当我们谈论map reduce或hadoop集群时经常看到。
    • 案例4:我认为案例4很少见。任务并发但不并行是很少见的。但这可能发生。例如,假设您的任务需要访问一个特殊的计算芯片,该芯片只能通过处理器1访问。因此,即使处理器2空闲并且处理器1正在执行其他任务,特殊计算任务也无法在处理器2上继续。
    • 病例5:也很罕见,但不像病例4那么罕见。非并发代码可以是由互斥体保护的关键区域。一旦启动,它必须执行到完成。然而,两个不同的关键区域可以在两个不同的处理器上同时进行。
    • 案例6:IMO,大多数关于并行或并发编程的讨论基本上都是关于案例6的。这是并行和并发执行的混合和匹配。

    并发和执行

    如果你明白为什么RobPike说并发性更好,你就必须明白原因是什么。您有一个非常长的任务,其中有多个等待期,您需要等待一些外部操作,如文件读取、网络下载。在他的演讲中,他所说的就是,"把这个长时间的连续任务分解,这样你就可以在等待的时候做一些有用的事情。"这就是为什么他用各种各样的gopher谈论不同的组织。好的。

    现在,go的力量来自于使用go关键字和频道使这种突破变得非常容易。此外,在运行时中有很好的底层支持来调度这些goroutine。好的。

    但本质上,并发性比并行性更好吗?好的。

    苹果比桔子好吗?好的。好啊。


    我喜欢RobPike的话:并发不是并行(更好!)(幻灯片)(谈话)

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

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

    Task

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

    Gophers

    并行性:如果至少有两个gopher同时工作或不工作,则以前的配置是并行的。


    加上其他人的话:

    并发性就像是让一个变戏法者玩多个球。不管怎么看,变戏法者每次只能接球/投球。平行是指有多个杂技演员同时杂耍球。


    假设你有一个程序有两个线程。程序可以通过两种方式运行:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Concurrency                 Concurrency + parallelism
    (Single-Core CPU)           (Multi-Core CPU)
     ___                         ___ ___
    |th1|                       |th1|th2|
    |   |                       |   |___|
    |___|___                    |   |___
        |th2|                   |___|th2|
     ___|___|                    ___|___|
    |th1|                       |th1|
    |___|___                    |   |___
        |th2|                   |   |th2|

    在这两种情况下,我们都有并发性,这仅仅是因为我们有多个线程在运行。

    如果我们在一台只有一个CPU核心的计算机上运行这个程序,操作系统将在两个线程之间切换,允许一次运行一个线程。

    如果我们在一台有多核CPU的计算机上运行这个程序,那么我们就能够同时并行地运行两个线程。


    并发性:如果两个或多个问题由单个处理器解决。alt text

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

    alt text


    我将尝试用一个有趣且易于理解的例子来解释。:)

    假设一个组织组织一个国际象棋比赛,其中10名选手(具有同等的国际象棋技能)将挑战一名职业冠军国际象棋选手。由于国际象棋是1:1的比赛,所以组织者必须及时有效地进行10场比赛,以便他们能尽快完成整个比赛。

    希望下面的场景可以很容易地描述这10个游戏的多种执行方式:

    1)连载-让我们假设专业人员一个接一个地与每个人玩,即与一个人开始和结束游戏,然后与下一个人开始下一个游戏,依此类推。换句话说,他们决定按顺序进行游戏。因此,如果一场比赛需要10分钟才能完成,那么10场比赛需要100分钟,同时假设从一场比赛过渡到另一场比赛需要6秒,那么10场比赛需要54秒(大约1分钟)。

    因此整个活动将在101分钟内完成(最差的方法)

    2)同时-假设职业选手轮到下一名选手,所以所有10名选手同时进行比赛,但职业选手一次不与两人在一起,他轮到下一名选手。现在假设职业球员轮到他需要6秒,而且职业球员B/W的两名球员的转换时间为6秒,所以回到第一名球员的总转换时间为1分钟(10x6秒)。因此,当他回到与谁一起开始比赛的第一人时,已经过了2分钟(冠军每转10分钟+10次转换2分钟)

    假设所有玩家都需要45秒来完成他们的回合,因此根据系列赛每局10分钟,游戏结束前的回合数应该是600/(45+6)=11轮(大约)

    因此,整个活动将在11个时间点内完成,10个玩家的转换时间为11×51+11×60秒=561+660=1221秒=20.35分钟(大约)

    从101分钟提高到20.35分钟(更好的方法)

    3)平行-让我们说组织者得到了一些额外的资金,因此决定邀请两名职业冠军选手(两人能力相同),并将相同的10名选手(挑战者)分成两组,每组5人,并分配给两名冠军,即每组1人。现在这两盘比赛是平行进行的,即至少有两名选手(每组一名)与各自组别的两名专业选手比赛。

    但是,在组内,一次只带一名玩家的专业玩家(即顺序),因此,如果不进行任何计算,您可以轻松推断整个事件将在101/2=50.5分钟内完成。

    看到从101分钟到50.5分钟的改进(好方法)

    4)并发+并行-在上面的场景中,假设两个冠军玩家将与各自组中的5个玩家同时玩(读第2点),所以现在组间的游戏是并行运行的,但组内的游戏是并行运行的。

    因此,一组中的游戏将在11个时间内完成,由玩家冠军+11个转换时间,玩家=11×51+11×30=600+330=930秒=15.5分钟(大约)

    所以整个事件(包括两个这样的并行运行组)将在15.5分钟内完成

    从101分钟提高到15.5分钟(最佳方法)

    注意:在上面的场景中,如果您用10个类似的作业替换10个玩家,用两个CPU核心替换两个专业玩家,那么下面的顺序仍然是正确的:

    串行>并行>并发>并发+并行

    (注意:对于其他情况,此顺序可能会更改,因为此顺序高度依赖于作业的相互依赖性、通信需要b/w作业和转换开销b/w作业)


    一致性:具有共享资源潜力的多个执行流

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

    副教派:将一个问题分成多个类似的块。

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


    简单例子:

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

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


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

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


    想象一下通过观看视频教程学习一种新的编程语言。您需要暂停视频,应用代码中所说的内容,然后继续观看。这是并发性。

    现在你是一个专业的程序员。你喜欢在编码的同时听平静的音乐。这就是平行性。

    享受。


    并发编程执行有两种类型:非并行并发编程和并行并发编程(也称为并行)。

    关键的区别在于,在人类看来,非并行并发中的线程似乎同时运行,但实际上并非如此。在非并行并发中,线程通过时间切片快速切换并轮流使用处理器。并行中有多个处理器可用,因此多个线程可以同时在不同的处理器上运行。enter image description here

    参考:编程语言中的并发性介绍


    把它看作是服务队列,其中服务器只能为队列中的第一个作业提供服务。

    1个服务器,1个作业队列(有5个作业)->没有并发性,没有并行性(只有一个作业要完成,队列中的下一个作业必须等待服务作业完成,并且没有其他服务器为其提供服务)

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

    2个或多个服务器,一个队列->并行(2个作业在同一时刻完成),但没有并发(服务器不共享时间,第3个作业必须等待其中一个服务器完成。)

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

    换句话说,并发性是共享时间来完成一个作业,它可能需要相同的时间来完成它的作业,但至少它可以提前开始。重要的是,工作可以被分割成更小的工作,这允许交错。

    并行性只需要更多并行运行的CPU、服务器、人员等就可以实现。

    请记住,如果资源是共享的,则无法实现纯粹的并行性,但这正是并发性最好的实际用途所在,因为它需要另一个不需要该资源的作业。


    并发性=>在与共享资源重叠的时间段内执行多个任务时(可能最大限度地提高资源利用率)。

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


    我将提供一个与这里的一些流行答案有点冲突的答案。在我看来,并发性是一个包含并行性的通用术语。并发性适用于不同任务或工作单元在时间上重叠的任何情况。并行性更具体地适用于在同一物理时间评估/执行不同工作单元的情况。并行性的原因在于加速了软件的开发,这些软件可以从多种物理计算资源中受益。另一个适合并发性的主要概念是交互性。当任务的重叠可以从外部世界观察到时,交互性就适用了。交互性的本质在于使软件能够响应现实世界中的实体,如用户、网络对等方、硬件外围设备等。

    并行性和交互性几乎完全独立于并发性。对于一个特定的项目,开发人员可能会同时关心这两者,或者两者都不关心。它们往往会被融合,尤其是因为令人憎恶的线给了一个相当方便的原始人两者兼而有之。

    关于并行性的更多细节:

    并行性存在于非常小的规模(例如处理器中的指令级并行)、中等规模(例如多核处理器)和大规模(例如高性能计算集群)中。近年来,由于多核处理器的发展,软件开发人员面临的暴露线程级并行性的压力越来越大。平行性与依赖的概念密切相关。依赖关系限制了可实现并行的程度;如果一个任务依赖于另一个任务,则无法并行执行两个任务(忽略推测)。

    程序员用来表示并行性的模式和框架有很多:管道、任务池、数据结构上的聚合操作("并行数组")。

    关于交互性的更多细节:

    最基本和最常见的交互方式是处理事件(即事件循环和处理程序/回调)。对于简单的任务来说,事件是伟大的。尝试用事件来完成更复杂的任务会导致堆栈撕裂(A.K.A.回调地狱;A.K.A.控制反转)。当您对事件感到厌烦时,您可以尝试更奇特的事情,如生成器、协程(a.k.a.异步/等待)或合作线程。

    为了热爱可靠的软件,如果你想要的是交互性,请不要使用线程。

    凝固不化

    我不喜欢RobPike的"并发性不是并行性,而是更好"的口号。并发性既不比并行性好也不比并行性差。并发性包括交互性,不能用更好/更差的方式与并行性进行比较。这就像是说"控制流比数据更好"。


    并行性是同时在multiple cores per CPUmultiple CPUs (on a single motherboard)上执行进程。

    并发性是指通过使用分配CPU时间(时间片)的调度算法,在single core CPU上实现并行性。进程是交错的。

    单位:

    • 一个CPU中有1个或多个内核(几乎都是现代处理器)
    • 主板上有1个或多个CPU(想想老式服务器)
    • 1个应用程序是1个程序(想想Chrome浏览器)
    • 一个程序可以有一个或多个进程(认为每个Chrome浏览器选项卡都是一个进程)
    • 1个进程可以有1个或多个来自1个程序的线程(Chrome选项卡在1个线程中播放YouTube视频,为注释部分生成另一个线程,为用户登录信息生成另一个线程)
    • 因此,一个程序可以有一个或多个执行线程
    • 1进程为thread(s)+allocated memory resources by OS(堆、寄存器、堆栈、类记忆


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

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

    串行/并行和顺序/并发特性是正交的。数字通信就是一个例子。在串行适配器中,数字信息是沿同一通信线路(例如一条线)临时(即按顺序)分布的。在并行适配器中,它也在并行通信线路(如多条线路)上被划分,然后在接收端重建。

    让我们想象一个有9个孩子的游戏。如果我们把它们当作一条链来处理,首先给出一条消息,然后在最后接收它,我们将拥有一个串行通信。更多的词组成信息,由一系列的通信单元组成。

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

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

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

    1
    2
    3
    I like ice-cream so much. > I like    > X > X > X > .... > ....
                              > ice-cream > X > X > X > ....
                              > so much   > X > X > X > ....

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

    在这两种情况下,假设孩子之间有一个完美的交流,结果是预先确定的。

    如果有其他人和您同时和第一个孩子说话,那么我们将有并发进程。我们不知道基础设施将考虑哪一个过程,所以最终结果还没有事先确定。


    并发是并行的一般形式。例如,并行程序也可以称为并发程序,但反向程序不正确。

  • 可以在单处理器(多个线程,由调度程序或线程池管理)上并发执行。

  • 在单处理器上不能并行执行,但在多处理器上可以并行执行。(每个处理器一个进程)

  • 分布式计算也是一个相关的话题,它也可以被称为并发计算,但反向计算并不是真的,比如并行性。

  • 有关详细信息,请阅读本研究论文并行编程的概念


    我真的很喜欢PaulButcher对这个问题的回答(他是七周内七个并发模型的作者):

    Although they’re often confused, parallelism and concurrency are
    different things. Concurrency is an aspect of the problem domain—your
    code needs to handle multiple simultaneous (or near simultaneous)
    events. Parallelism, by contrast, is an aspect of the solution
    domain—you want to make your program run faster by processing
    different portions of the problem in parallel. Some approaches are
    applicable to concurrency, some to parallelism, and some to both.
    Understand which you’re faced with and choose the right tool for the
    job.


    我真的很喜欢另一个答案的图形表示法-我认为它比上面的许多答案更能回答问题。

    并行与并发当两个线程并行运行时,它们都同时运行。例如,如果我们有两个线程A和B,那么它们的并行执行如下所示:

    CPU 1:A------------------------->

    CPU 2:B------------------------->

    当两个线程同时运行时,它们的执行重叠。重叠可以通过以下两种方式之一发生:要么线程同时执行(即并行执行,如上所述),要么线程的执行在处理器上交错执行,就像这样:

    CPU 1:A---------->B----->A----->B----->

    因此,就我们的目的而言,并行性可以看作是并发性的一种特殊情况。

    资料来源:另一个答案

    希望有帮助。


    "并发"是指有多个正在进行的事情。

    "并行性"是指并行的事情同时进行。

    无并行的并发示例:

    • 一个内核上有多个线程。
    • Win32消息队列中有多条消息。
    • 多个SqlDataReader在火星连接上。
    • 浏览器选项卡中有多个javascript承诺。

    然而,请注意,并发性和并行性之间的区别常常是一个透视问题。从执行代码的角度(可观察的效果)来看,上述示例是不平行的。但即使在一个内核中,也存在指令级的并行性。有些硬件与CPU并行工作,完成后中断CPU。当您执行窗口过程或事件处理程序时,GPU可能正在绘制到屏幕上。当您仍在获取前一个查询的结果时,DBMS可能正在遍历B树以进行下一个查询。浏览器可以在执行Promise.resolve()时进行布局或联网。等等。

    那就这样吧。世界一如既往的混乱;)


    并发性可能涉及同时运行或不运行的任务(它们确实可以在单独的处理器/核心中运行,但也可以在"滴答声"中运行)。重要的是并发性总是指完成一项更大的任务。所以基本上它是一些计算的一部分。你必须对你能同时做什么,不能做什么以及如何同步很聪明。

    并行性意味着你只是同时做一些事情。他们不需要成为解决一个问题的一部分。例如,线程可以分别解决一个问题。当然,同步的东西也适用,但从不同的角度来看。


    Concurrent programming regards operations that appear to overlap and is primarily concerned with the complexity that arises due to non-deterministic control flow. The quantitative costs associated with concurrent programs are typically both throughput and latency. Concurrent programs are often IO bound but not always, e.g. concurrent garbage collectors are entirely on-CPU. The pedagogical example of a concurrent program is a web crawler. This program initiates requests for web pages and accepts the responses concurrently as the results of the downloads become available, accumulating a set of pages that have already been visited. Control flow is non-deterministic because the responses are not necessarily received in the same order each time the program is run. This characteristic can make it very hard to debug concurrent programs. Some applications are fundamentally concurrent, e.g. web servers must handle client connections concurrently. Erlang is perhaps the most promising upcoming language for highly concurrent programming.

    Parallel programming concerns operations that are overlapped for the specific goal of improving throughput. The difficulties of concurrent programming are evaded by making control flow deterministic. Typically, programs spawn sets of child tasks that run in parallel and the parent task only continues once every subtask has finished. This makes parallel programs much easier to debug. The hard part of parallel programming is performance optimization with respect to issues such as granularity and communication. The latter is still an issue in the context of multicores because there is a considerable cost associated with transferring data from one cache to another. Dense matrix-matrix multiply is a pedagogical example of parallel programming and it can be solved efficiently by using Straasen's divide-and-conquer algorithm and attacking the sub-problems in parallel. Cilk is perhaps the most promising language for high-performance parallel programming on shared-memory computers (including multicores).

    复制自我的答案:https://stackoverflow.com/a/3982782


    (我很惊讶这样一个基本问题多年来没有得到正确而巧妙的解决…)

    简而言之,并发性和并行性都是计算的属性。

    至于区别,下面是罗伯特·哈珀的解释:

    The first thing to understand is parallelism has nothing to do with concurrency. Concurrency is concerned with nondeterministic composition of programs (or their components). Parallelism is concerned with asymptotic efficiency of programs with deterministic behavior. Concurrency is all about managing the unmanageable: events arrive for reasons beyond our control, and we must respond to them. A user clicks a mouse, the window manager must respond, even though the display is demanding attention. Such situations are inherently nondeterministic, but we also employ pro forma nondeterminism in a deterministic setting by pretending that components signal events in an arbitrary order, and that we must respond to them as they arise. Nondeterministic composition is a powerful program structuring idea. Parallelism, on the other hand, is all about dependencies among the subcomputations of a deterministic computation. The result is not in doubt, but there are many means of achieving it, some more efficient than others. We wish to exploit those opportunities to our advantage.

    它们可以是程序中的各种正交属性。阅读此博客文章了解更多插图。这篇文章更详细地讨论了编程中组件的区别,比如线程。

    注意,线程或多任务都是为更具体的目的服务的计算的实现。它们可以与并行性和并发性相关,但不是以一种基本的方式。因此,它们不是开始解释的好条目。

    另一个亮点是:(物理)"时间"几乎与这里讨论的属性无关。时间只是实现测量的一种方式,显示了测量的性质的重要性,但离本质还很远。再想一想"时间"在时间复杂性中的作用——这或多或少是相似的,在这种情况下,即使是度量也往往更为重要。


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

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

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

    希望这有帮助!


    平行度:让多个线程执行相似的任务,这些任务在数据和资源方面相互独立,它们需要这样做。谷歌爬虫可以产生数千个线程,每个线程都可以独立完成任务。

    并发性:当您共享了数据,线程间共享了资源时,并发就出现了。在事务性系统中,这意味着您必须使用一些技术(如锁、信号量等)来同步代码的关键部分。


    太好了,让我用一个场景来展示我的理解。假设有3个孩子的名字:A,B,C,A和B,说话,C,听着。对于A和B,它们是平行的:我是A.。B:我是B.。

    但是对于C来说,他的大脑必须同时接受A和B的过程,这可能是:我是A。


    这个来源的解释对我很有帮助:

    Concurrency is related to how an application handles multiple tasks it
    works on. An application may process one task at at time
    (sequentially) or work on multiple tasks at the same time
    (concurrently).

    Parallelism on the other hand, is related to how an application
    handles each individual task. An application may process the task
    serially from start to end, or split the task up into subtasks which
    can be completed in parallel.

    As you can see, an application can be concurrent, but not parallel.
    This means that it processes more than one task at the same time, but
    the tasks are not broken down into subtasks.

    An application can also be parallel but not concurrent. This means
    that the application only works on one task at a time, and this task
    is broken down into subtasks which can be processed in parallel.

    Additionally, an application can be neither concurrent nor parallel.
    This means that it works on only one task at a time, and the task is
    never broken down into subtasks for parallel execution.

    Finally, an application can also be both concurrent and parallel, in
    that it both works on multiple tasks at the same time, and also breaks
    each task down into subtasks for parallel execution. However, some of
    the benefits of concurrency and parallelism may be lost in this
    scenario, as the CPUs in the computer are already kept reasonably busy
    with either concurrency or parallelism alone. Combining it may lead to
    only a small performance gain or even performance loss.


    派克的"并发性"概念是一个有意设计和实现的决定。具有并发能力的程序设计可能表现出行为"并行性",也可能不表现出行为"并行性";这取决于运行时环境。

    您不想让一个不是为并发而设计的程序展示并行性。:-)但是如果它是相关因素(功耗、性能等)的净收益,那么您需要一个最大限度的并发设计,以便主机系统可以在可能的情况下并行执行。

    派克的Go编程语言极端地说明了这一点:他的函数都是可以同时正确运行的线程,也就是说,调用一个函数总是创建一个线程,如果系统有能力的话,它将与调用方并行运行。拥有成百上千个线程的应用程序在他的世界中是非常普通的。(我不是专家,这只是我的看法。)


    并发性简单意味着有多个任务正在运行(不需要并行)。例如,assumer我们在任何时候都有3个任务:可能有多个任务在运行,或者所有任务都在同时运行。

    并行性意味着它们实际上是并行运行的。所以在这种情况下,这三个都必须同时运行。


    "并发"就是同时做任何事情。它们可以是不同的东西,也可以是相同的东西。尽管没有公认的答案,但这并不是"同时出现",而是真正的同时。您需要多个CPU核心,要么在一个主机中使用共享内存,要么在不同的主机上使用分布式内存,以运行并发代码。同时运行的3个不同任务的管道就是一个例子:任务级别2必须等待任务级别1完成的单元,任务级别3必须等待任务级别2完成的单元。另一个例子是1生产者与1消费者,或许多生产者与1消费者,读者与作者,等等的并发。

    "平行"就是同时做同样的事情。它是并发的,但更进一步地说,它是同时发生的相同行为,而且通常是在不同的数据上发生的。矩阵代数通常可以并行化,因为有相同的操作重复运行:例如,一个矩阵的列和可以同时使用相同的行为(和)但在不同的列上计算。在可用处理器核心之间划分(拆分)列是一种常见的策略,这样每个处理器核心处理的工作量(列数)几乎相同。另一种分解工作的方法是一袋任务,其中完成工作的工人会回到一个经理那里,他会把工作交出来,动态地得到更多的工作,直到所有的工作都完成。票务算法是另一种。

    不仅数字代码可以并行化。文件常常可以并行处理。在自然语言处理应用程序中,对于数百万个文档文件中的每一个,您可能需要计算文档中令牌的数量。这是并行的,因为您正在为每个文件计算令牌,这是相同的行为。

    换句话说,并行就是同时执行相同的行为。同时意味着同时,但不一定是相同的行为。并行是一种特殊的并发,在这种并发中,相同的事情同时发生。

    例如,术语将包括原子指令、关键部分、互斥、自旋等待、信号量、监视器、屏障、消息传递、映射减少、心跳、环、票务算法、线程、MPI、OpenMP。

    格雷戈里·安德鲁斯的著作是一本关于它的顶级教科书:多线程、并行和分布式编程。


    仅仅通过查阅字典,您就可以看到并发(来自拉丁语)意味着一起运行、聚合、同意;因此需要同步,因为在相同的资源上存在竞争。平行(从希腊语)意味着在侧面复制;从而在同一时间做同样的事情。