并发和并行有什么区别?
内容:有可能共享资源的多个执行流
例如:两个线程竞争一个I/O端口。
并行:将问题拆分为多个相似的块。
例如:通过对文件的每一半运行两个进程来解析大文件。
并发是指两个或多个任务可以在重叠的时间时期中启动、运行和完成。这并不一定意味着它们都将运行在同一瞬间。例如,单核机器上的多任务处理。
并行是当任务字面上同时运行时,例如,在多核处理器上。
引用Sun的多线程编程指南:
并发:至少有两个线程正在进行时存在的一种条件。一种更通用的并行形式,可以包括时间切片作为虚拟并行的一种形式。
并行:至少两个线程同时执行时出现的条件。
它们解决了不同的问题。并发解决了CPU资源稀缺和任务众多的问题。因此,你通过代码创建线程或独立的执行路径,以便在稀缺资源上共享时间。直到最近,由于CPU可用性,并发一直主导着讨论。
并行解决了找到足够的任务和适当的任务(可以正确拆分的任务)并将它们分配到大量CPU资源上的问题。并行一直存在,但由于多核处理器如此便宜,它正成为最前沿。
并发:如果单个处理器解决了两个或多个问题。
并行性:如果一个问题由多个处理器解决。
我喜欢Rob Pike的演讲:并发不是并行(它更好!)(幻灯片)(谈话)
Rob通常会谈论Go,并且通常会以可视化和直观的解释来解决并发与并行的问题!以下是一个简短的摘要:
任务:让我们烧掉一堆过时的语言手册!一次一个!
并发:任务有很多并发分解!一个例子:
并行性:如果至少有2个地鼠同时工作或不工作,则前面的配置并行发生。
补充一下别人说过的话:
并发就像让杂耍演员杂耍很多球。不管看起来如何,杂耍演员一次只接/扔一个球。并行是让多个杂耍演员同时杂耍球。
并发=>当多个任务在共享资源的重叠时间段内执行时(可能最大化资源利用率)。
并行=>当单个任务被分成多个可以同时执行的简单独立子任务时。
在电子学中,串行和并行代表一种静态拓扑,决定电路的实际行为。当没有并发时,并行是确定性的。
为了描述动态,我们使用了术语与时间有关的现象和并发。例如,可能通过任务的某个序列获得了某个结果(例如菜谱)。当我们与某人交谈时,我们正在产生一系列单词。然而,在现实中,许多其他过程发生在同一时刻,因此,同意到某个动作的实际结果。如果许多人同时在交谈,并发会谈可能会干扰我们的序列,但这种干扰的结果是未知的。并发引入了不确定性。
串行/并行和顺序/并发表征是正交的。这方面的一个例子是在数字通信中。在串行适配器中,数字消息在时间上(即顺序)沿着同一通信线路(例如一条线)分布。在并行适配器中,这也在并行通信线路(例如多条线)上划分,然后在接收端重建。
让我们想象一个有9个孩子的游戏。如果我们把它们当作一条链,在第一个发出信息,在最后收到信息,我们就会有一个串行通信。更多的单词组成了信息,由一系列通信单元组成。
I like ice-cream so much. > X > X > X > X > X > X > X > X > X > ....
这是在串行基础设施上复制的顺序过程。
现在,让我们想象把孩子们分成3组。我们把这个短语分成三个部分,第一个给我们左边的线的孩子,第二个给中心线的孩子,等等。
I like ice-cream so much. > I like > X > X > X > .... > ....> ice-cream > X > X > X > ....> so much > X > X > X > ....
这是在并行基础设施上复制的顺序过程(尽管仍然部分序列化)。
在这两种情况下,假设孩子之间有一个完美的沟通,结果是确定提前。
如果有其他人与您同时与第一个孩子交谈,那么我们将有并行进程。我们不知道基础设施将考虑哪个过程,因此最终结果是提前未确定。
将其视为服务队列,其中服务器只能服务队列中的第一个作业。
1台服务器,1个作业队列(有5个作业)->没有并发,没有并行(只有一个作业被服务完成,队列中的下一个作业必须等到服务的作业完成,并且没有其他服务器为其提供服务)
1台服务器,2个或更多不同的队列(每个队列有5个作业)->并发(因为服务器与队列中的所有第一个作业共享时间,相等或加权),仍然没有并行性,因为在任何时刻,都有一个且只有一个作业被服务。
2个或更多服务器,一个Queue->并行(2个作业在同一时刻完成)但没有并发(服务器不共享时间,第3个作业必须等到其中一个服务器完成。)
2个或多个服务器,2个或多个不同的队列->并发和并行
换句话说,并发是共享时间来完成一项工作,它可能需要相同的时间来完成它的工作,但至少它可以提前开始。重要的是,作业可以被切成更小的作业,这允许交错。
并行性是通过更多并行运行的CPU、服务器、人员等来实现的。
请记住,如果资源是共享的,则无法实现纯并行性,但这是并发具有最佳实际用途的地方,占用了不需要该资源的另一项工作。
太好了,让我用一个场景来展示我所理解的。假设有三个孩子叫:A,B,C,A和B说话,C听。对于A和B,它们是平行的:A:我是A。我是B
但是对于C,他的大脑必须采取并发进程来倾听A和B,它可能:我是A我是B
我将提供一个与这里的一些流行答案有一点冲突的答案。在我看来,并发是一个包括并行的通用术语。0适用于不同任务或工作单元在时间上重叠的任何情况。1更具体地适用于在同一物理时间评估/执行不同工作单元的情况。并行存在的理由是加速可以从多个物理计算资源中受益的软件。适合并发的另一个主要概念是交互性。2适用于从外部世界可以观察到任务重叠的情况。交互性存在的理由是制作响应真实世界实体(如用户、网络对等体、硬件外围设备等)的软件。
并行性和交互性几乎完全是并发的独立维度。对于一个特定的项目,开发人员可能会关心其中的任何一个,或者两者都不关心。它们往往会被混为一谈,尤其是因为线程这种令人憎恶的东西提供了一个相当方便的原语来做这两件事。
关于并行的更多细节:
并行存在于极小规模(例如处理器中的指令级并行)、中等规模(例如多核处理器)和大型(例如高性能计算集群)。近年来,由于多核处理器的增长,软件开发人员暴露更多线程级并行的压力有所增加。并行性与依赖的概念密切相关。依赖限制了并行的实现程度;如果两个任务相互依赖,就不能并行执行(忽略猜测)。
程序员使用许多模式和框架来表达并行性:管道、任务池、数据结构上的聚合操作(“并行数组”)。
关于交互性的更多细节:
最基本也是最常见的交互方式是使用事件(即事件循环和处理程序/回调)。对于简单的任务,事件很棒。尝试使用事件执行更复杂的任务会进入堆栈翻录(又名回调地狱;又名控制反转)。当你厌倦了事件时,你可以尝试更奇特的东西,如生成器、协程(又名异步/等待)或合作线程。
出于对可靠软件的热爱,如果您想要的是交互性,请不要使用线程。
脾气古怪
我不喜欢Rob Pike的“并发不是并行;这是更好的”口号。并发既不比并行更好,也不比并行更差。并发包括交互性,不能以更好/更差的方式与并行进行比较。这就像说“控制流比数据更好”。
混淆的存在是因为这两个词的字典含义几乎相同:
然而,它们在计算机科学和编程中的使用方式却截然不同。以下是我的解释:
那么,上述定义是什么意思呢?
我将用一个现实世界的类比来澄清。假设你必须在一天内完成两项非常重要的任务:
现在的问题是,任务1要求你去一个极其官僚的政府办公室,排队4个小时才能拿到护照。同时,任务2是你的办公室要求的,这是一项关键任务。两者都必须在特定的一天完成。
通常,你会开车去护照办公室2个小时,排队4个小时,完成任务,开车回来两个小时,回家,再醒5个小时,完成演示。
但是你很聪明。你提前计划。你随身携带一台笔记本电脑,在排队等候的时候,你开始准备你的演示文稿。这样,一旦你回到家,你只需要多工作1个小时,而不是5个小时。
在这种情况下,这两项任务都由您完成,只是部分完成。您在排队等候时中断了护照任务并处理演示文稿。当您的号码被叫到时,您中断了演示文稿任务并切换到护照任务。由于这两项任务的可中断性,节省时间基本上是可能的。
并发,IMO,可以理解为酸中的“隔离”属性。如果子事务可以以任何交错方式执行,并且最终结果与两个任务顺序完成相同,则两个数据库事务被视为隔离的。请记住,对于护照和演示任务,你是唯一的刽子手。
现在,既然你是个聪明的家伙,你显然是上级,而且你有一个助手。所以,在你离开开始护照任务之前,你打电话给他,告诉他准备演示文稿的初稿。你花了一整天的时间完成护照任务,回来看你的邮件,你找到了演示文稿。他做得很扎实,再过两个小时就做了一些编辑,你完成了它。
现在,你的助手和你一样聪明,他可以在独立上工作,而不需要不断要求你澄清。因此,由于任务的独立性,它们同时由两个不同的刽子手执行。
还在吗?好吧…
记住你的护照任务,你必须在哪里排队?由于是你护照,你的助手不能排队等你。因此,护照任务有可中断性(你可以在排队时停止它,当你的号码被叫到时再恢复),但没有独立性(你的助手不能代替你等待)。
假设政府办公室有安全检查进入场所。在这里,你必须删除所有电子设备并将其提交给官员,他们只有在你完成任务后才归还你的设备。
在这种情况下,护照任务既不是独立也不是可中断。即使你在排队等候,你也不能做其他事情,因为你没有必要的设备。
同样,假设演示文稿本质上是高度数学化的,你需要100%的注意力至少5个小时。即使你随身携带笔记本电脑,你也不能在排队等待护照任务时这样做。
在这种情况下,演示任务是独立(你或你的助手可以投入5个小时的集中精力),但不是可中断。
现在,假设除了让你的助手参加演示之外,你还随身携带了一台笔记本电脑来完成护照任务。在排队等待的时候,你看到你的助手已经在共享的甲板上创建了前10张幻灯片。你发送了对他工作的评论,并进行了一些更正。后来,当你回家时,你只需要15分钟,而不是2小时来完成草稿。
这是可能的,因为演示任务有独立性(你们中的任何一个都可以执行)和可中断性(您可以停止它并稍后恢复它)。因此,您同时执行了两者个任务,并并行执行了演示任务。
比方说,除了过于官僚主义之外,政府办公室也是腐败的。因此,你可以出示你的身份证件,输入它,开始排队等待你的号码被呼叫,贿赂警卫和其他人在排队时占据你的位置,偷偷溜出去,在你的号码被呼叫之前回来,然后继续等待。
在这种情况下,您可以同时并行执行护照和演示任务。您可以偷偷溜出去,您的职位由您的助手担任。然后,您可以同时处理演示文稿等。
在计算世界中,以下是每个案例的典型示例场景:
如果你明白为什么Rob Pike说并发更好,你必须明白原因是什么。你有一个非常长的任务,其中有多个等待期,你在等待一些外部操作,如文件读取,网络下载。在他的讲座中,他所说的只是,“打破这个长时间连续的任务,这样你就可以在等待的时候做一些有用的事情。”这就是为什么他和各种地鼠谈论不同的组织。
现在,Go的优势来自于使用go关键字和通道使这个突破变得非常容易。此外,运行时中还有出色的底层支持来安排这些goroutines。
go
但本质上,并发比并行更好吗?
苹果比橘子好吗?
并发简单意味着多个任务正在运行(不需要并行)。例如,假设我们在任何时候都有3个任务:可能不止一个正在运行,也可能所有任务都在同一时间运行。
并行意味着它们实际上是并行运行的。所以在这种情况下,所有三个必须同时运行。
简单的例子:
并发是:“两个队列访问一台ATM机”
并行是:“两个队列和两个ATM机”
我将尝试用一个有趣且易于理解的例子来解释。:)
假设是指一个组织组织了一场国际象棋比赛,10名玩家(具有相同的国际象棋技能)将挑战职业冠军的国际象棋玩家。由于国际象棋是1:1的游戏,因此组织者必须以及时有效的方式进行10场比赛,以便他们能够尽快完成整个事件。
希望以下场景可以轻松描述进行这10个游戏的多种方式:
1)系列-假设专业人士一个接一个地与每个人一起玩,即与一个人开始和完成游戏,然后与下一个人开始下一场游戏,依此类推。换句话说,他们决定按顺序进行游戏。因此,如果一场比赛需要10分钟才能完成,那么10场比赛将需要100分钟,还假设从一场比赛过渡到另一场比赛需要6秒,那么10场比赛将是54秒(约1分钟)。
所以整个活动大约在101分钟内完成(最坏的方法)
2)同时-假设职业玩家完成他的回合并移动到下一个玩家,因此所有10名玩家同时玩,但职业玩家一次不是和两个人在一起,他完成他的回合并移动到下一个玩家。现在假设一名职业玩家完成他的回合需要6秒,而且一名职业玩家两个玩家的过渡时间是6秒,因此回到第一个玩家的总过渡时间将是1分钟(10x6秒)。因此,当他回到第一个开始活动的人时,已经过去了2分钟(10xtime_per_turn_by_champion+10xtransition_time=2分钟)
假设所有玩家需要45秒来完成他们的回合,所以基于从连环事件开始的每场比赛10分钟,游戏结束前的回合数应该是600/(45+6)=11轮(大约)
所以整个事件将在11xtime_per_turn_by_player_&_champion+11xtransition_time_across_10_players=11x51+11x60sec=561+660=1221sec=20.35min(大约)完成
查看从101分钟到20.35分钟的改进(更好的方法)
3)并行-假设组织者获得了一些额外的资金,因此决定邀请两名职业冠军球员(能力相同)并将相同的10名玩家(挑战者)分成两组,每组5人,并将他们分配给两名冠军,即每组一个。现在活动在这两组中并行进行,即至少有两名玩家(每组一名)与各自组中的两名职业玩家对抗。
然而,在小组内,职业球员一次(即顺序)采取一名球员,因此无需任何计算,您可以轻松推断整个事件将在101/2=50.5分钟内完成
查看从101分钟到50.5分钟的改进(方法不错)
4)并行+并行-在上述场景中,假设两个冠军玩家将与各自组中的5名玩家同时进行游戏(阅读第2点),所以现在跨组的游戏并行运行,但在组内,它们同时运行。
所以一组游戏大约在11xtime_per_turn_by_player_&_champion+11xtransition_time_across_5_players=11x51+11x30=600+330=930sec=15.5分钟(大约)
所以整个活动(涉及两个这样的平行跑团)大约在15.5分钟内完成
查看从101分钟到15.5分钟的改进(最佳方法)
注:在上面的场景中,如果你用10个类似的工作替换10个玩家,用两个CPU内核替换两个职业玩家,那么以下顺序仍然是true:
串行>并行>并发>并发+并行
(注意:此顺序可能会因其他场景而更改,因为此顺序高度依赖于作业的相互依赖性,作业之间的通信需求和作业之间的转换开销)
假设你有一个有两个线程的程序。该程序可以通过两种方式运行:
Concurrency Concurrency + parallelism(Single-Core CPU) (Multi-Core CPU)___ ___ ___|th1| |th1|th2|| | | |___||___|___ | |___|th2| |___|th2|___|___| ___|___||th1| |th1||___|___ | |___|th2| | |th2|
在这两种情况下,我们都有并发,因为我们有多个线程在运行。
如果我们在具有单个CPU内核的计算机上运行此程序,操作系统将在两个线程之间切换,允许一次运行一个线程。
如果我们在具有多核CPU的计算机上运行此程序,那么我们将能够在并行中同时并排运行两个线程。
并发是并行的广义形式。例如并行程序也可以称为并发,但反向不是真的。
在单处理器上可以并发执行(多线程,由调度程序或线程池管理)
不能在单个处理器上并行执行,而是在多个处理器上并行执行。(每个处理器一个进程)
分布式计算也是一个相关的话题,它也可以被称为并发计算,但反向不是真的,就像并行一样。
有关详细信息,请阅读此研究论文并发编程的概念
派克的“并发”概念是一种有意的设计和实现决策。支持并发的程序设计可能会或可能不会表现出行为“并行”;它取决于运行时环境。
你不希望一个不是为并发而设计的程序表现出并行性。:-)但是在某种程度上,它是相关因素(功耗、性能等)的净收益,你想要一个最大并发的设计,以便主机系统可以在可能的情况下并行化它的执行。
派克的Go编程语言极端地说明了这一点:他的函数都是可以正确并发运行的线程,即调用一个函数总是创建一个线程,如果系统有能力的话,这个线程将与调用者并行运行。在他的世界里,一个拥有数百甚至数千个线程的应用程序是非常普通的。(我不是围棋专家,这只是我的看法。)
只要查一查字典,你就会发现,并发(来自拉丁语)的意思是一起运行,收敛,同意;因此需要同步,因为在相同的资源上存在竞争。并行(来自希腊语)的意思是在一边复制;同时做同样的事情。
我真的很喜欢保罗·布彻对这个问题的回答(他是七周内的七个并发模型的作者):
虽然它们经常被混淆,但并行和并发是不同的东西并发是问题域的一个方面-你的代码需要处理多个同时(或接近同时)相反,并行是解决方案的一个方面域-您希望通过处理使您的程序运行得更快问题的不同部分并行。一些方法是适用于并发,有些适用于并行,有些适用于两者。了解您面临的问题并选择正确的工具工作。
并发可以涉及同时运行或不运行的任务(它们确实可以在单独的处理器/内核中运行,但也可以在“滴答”中运行)。重要的问题是并发总是引用做一个更大的任务的一部分。所以基本上它是一些计算的一部分。你必须聪明地知道什么可以同时做,什么不能做,以及如何同步。
并行意味着你只是同时做一些事情。它们不需要成为解决一个问题的一部分。例如,你的线程可以各自解决一个问题。当然同步的东西也适用,但从不同的角度来看。
想象一下通过观看视频教程学习一种新的编程语言。您需要暂停视频,应用代码中所说的内容,然后继续观看。这就是并发。
现在你是一个专业的程序员。你喜欢在编码时听平静的音乐。这就是Parallelism。
正如Andrew Gerrand在GoLang博客中所说
并发是指同时处理很多事情。并行一次做很多事情
好好享受。
并行:有多个线程执行类似的任务,这些线程在执行任务所需的数据和资源方面相互独立。例如:谷歌爬虫可以产生数千个线程,每个线程都可以独立完成它的任务。
并发:当您在线程之间共享数据、共享资源时,并发就会出现。在事务系统中,这意味着您必须使用锁、信号量等技术同步代码的关键部分。
并发程序涉及看起来重叠的操作,主要与非确定控制流引起的复杂性有关。并发程序相关的定量成本通常是吞吐量和延迟。并发程序通常是IO绑定的,但并非总是如此,例如并发垃圾收集器完全在CPU上。并发程序的教学示例是网络爬虫。当下载结果变得可用时,该程序发起对网页的请求并并发接受响应,积累一组已经访问过的页面。控制流是不确定的,因为每次程序运行时响应不一定以相同的顺序接收。这一特性使得调试并发程序变得非常困难。一些应用程序从根本上说是并发的,例如Web服务器必须并发处理客户端连接。Erlang也许是未来最有前途的高并发编程语言。 并行编程关注的是为了提高吞吐量这一特定目标而重叠的操作。通过使控制流确定性来规避并发编程的困难。通常,程序生成的子任务集并行运行,父任务只有在每个子任务完成后才继续。这使得并行程序更容易调试。并行编程的困难部分是在颗粒度和通信等问题上的性能优化。后者在多核环境中仍然是一个问题,因为将数据从一个缓存传输到另一个缓存有相当大的成本。密集矩阵-矩阵乘法是并行编程的一个教学示例,它可以通过使用Straasen的分治算法和并行攻击子问题来有效地解决。Cilk可能是共享内存计算机(包括多核)上高性能并行编程最有前途的语言。
并发程序涉及看起来重叠的操作,主要与非确定控制流引起的复杂性有关。并发程序相关的定量成本通常是吞吐量和延迟。并发程序通常是IO绑定的,但并非总是如此,例如并发垃圾收集器完全在CPU上。并发程序的教学示例是网络爬虫。当下载结果变得可用时,该程序发起对网页的请求并并发接受响应,积累一组已经访问过的页面。控制流是不确定的,因为每次程序运行时响应不一定以相同的顺序接收。这一特性使得调试并发程序变得非常困难。一些应用程序从根本上说是并发的,例如Web服务器必须并发处理客户端连接。Erlang也许是未来最有前途的高并发编程语言。
并行编程关注的是为了提高吞吐量这一特定目标而重叠的操作。通过使控制流确定性来规避并发编程的困难。通常,程序生成的子任务集并行运行,父任务只有在每个子任务完成后才继续。这使得并行程序更容易调试。并行编程的困难部分是在颗粒度和通信等问题上的性能优化。后者在多核环境中仍然是一个问题,因为将数据从一个缓存传输到另一个缓存有相当大的成本。密集矩阵-矩阵乘法是并行编程的一个教学示例,它可以通过使用Straasen的分治算法和并行攻击子问题来有效地解决。Cilk可能是共享内存计算机(包括多核)上高性能并行编程最有前途的语言。
来自我的答案:https://stackoverflow.com/a/3982782
这个来源的解释对我很有帮助:
并发与应用程序如何处理多个任务有关一个应用程序一次可以处理一个任务(顺序)或同时处理多个任务(同时)。 另一方面,并行性与应用程序如何处理每个单独的任务。应用程序可以处理该任务从开始到结束,或者将任务拆分为子任务可以并行完成。 如您所见,应用程序可以是并发的,但不能是并行的。这意味着它同时处理多个任务,但这些任务没有被分解成子任务。 应用程序也可以并行但不能并发。这意味着应用程序一次只能处理一个任务,而这个任务被分解为可以并行处理的子任务。 此外,应用程序既不能并发也不能并行。这意味着它一次只能在一个任务上工作,并且任务是永远不会分解为并行执行的子任务。 最后,应用程序也可以是并发和并行的,在它可以同时处理多个任务,也可以中断将每个任务分解为子任务以并行执行。但是,其中一些在这种情况下,并发和并行的好处可能会丢失场景,因为计算机中的CPU已经保持相当繁忙单独使用并发或并行。组合它可能会导致只有很小的性能提升甚至性能损失。
并发与应用程序如何处理多个任务有关一个应用程序一次可以处理一个任务(顺序)或同时处理多个任务(同时)。
另一方面,并行性与应用程序如何处理每个单独的任务。应用程序可以处理该任务从开始到结束,或者将任务拆分为子任务可以并行完成。
如您所见,应用程序可以是并发的,但不能是并行的。这意味着它同时处理多个任务,但这些任务没有被分解成子任务。
应用程序也可以并行但不能并发。这意味着应用程序一次只能处理一个任务,而这个任务被分解为可以并行处理的子任务。
此外,应用程序既不能并发也不能并行。这意味着它一次只能在一个任务上工作,并且任务是永远不会分解为并行执行的子任务。
最后,应用程序也可以是并发和并行的,在它可以同时处理多个任务,也可以中断将每个任务分解为子任务以并行执行。但是,其中一些在这种情况下,并发和并行的好处可能会丢失场景,因为计算机中的CPU已经保持相当繁忙单独使用并发或并行。组合它可能会导致只有很小的性能提升甚至性能损失。
“并发”是指存在多个事物进行中。
“并行”是指并发的事情正在进行与此同时。
没有并行的并发示例:
SqlDataReader
然而,请注意,并发和并行之间的区别通常是一个视角问题。从执行代码的可观察效果的角度来看,上述示例是不并行的。但即使在单个内核中也存在指令级并行。有些硬件与CPU并行做事,然后在完成后中断CPU。当你窗口过程或事件处理程序被执行时,GPU可能正在绘制到屏幕上。当你仍在获取前一个查询的结果时,DBMS可能正在遍历B树以进行下一个查询。当你的Promise.resolve()被执行时,浏览器可能正在做布局或网络。等等…
Promise.resolve()
所以你走了。世界一如既往地混乱;)
在我看来,理解这两者的最简单、最优雅的方式是这样的。并发允许交错执行,因此可以给出并行性的错觉。这意味着并发系统可以在你用Word编写文档的同时运行你的YouTube视频。底层操作系统是一个并发系统,使这些任务能够交错执行。因为计算机执行指令的速度如此之快,这给人一种同时做两件事的感觉。
并行是这样的事情真的是并行。在上面的示例中,您可能会发现视频处理代码在单个内核上执行,而Word应用程序在另一个内核上运行。请注意,这意味着并发程序也可以并行!
为什么不能并行呢?一个原因是并发是0号程序的一种方式,是为了促进关注点分离而做出的设计决策,而并行通常是以性能的名义使用的。另一个原因是有些事情从根本上不能完全并行完成。例如,在队列的后面添加两件事情——你不能同时插入两件事情。必须有一件事在前面,另一件在后面,否则你会弄乱队列。尽管我们可以交错执行(因此我们得到了一个并发队列),但你不能让它并行。
希望这有帮助!
我真的很喜欢这个来自另一个答案的图形表示-我认为它比上面的很多答案更好地回答了这个问题
并行与并发当两个线程并行运行时,它们同时运行。例如,如果我们有两个线程,A和B,那么它们的并行执行如下所示:
CPU 1: ------------------------->;
CPU 2: B ------------------------->;
当两个线程同时运行时,它们的执行会重叠。重叠可以通过以下两种方式之一发生:线程同时执行(即如上所述并行),或者它们的执行在处理器上交错执行,如下所示:
CPU 1:A ----------->;B ---------->;A ----------->;B ---------->;
所以,为了我们的目的,并行可以被认为是一种特殊的并发情况
来源:另一个答案在这里
希望有帮助。
(我很惊讶这样一个基本问题多年来没有得到正确和整齐的解决……)
简而言之,并发和并行都是计算的属性。
至于区别,这里是罗伯特·哈珀的解释:
首先要理解的是并行与并发无关。并发关心的是不确定成分的程序(或它们的组件)。并行关心的是渐近效率的程序的确定性行为。并发就是管理不可管理的事情:事件的发生是由于我们无法控制的原因,我们必须对它们做出响应。用户点击鼠标,窗口管理器必须做出响应,即使显示需要关注。这种情况本质上是不确定的,但我们也在确定性设置中使用了形式的不确定性,假装组件以任意顺序发出事件信号,并且我们必须在它们出现时做出响应。不确定性组合是一个强大的程序结构思想。另一方面,并行性是关于确定性计算的子计算之间的依赖关系。结果是毫无疑问的,但有很多方法可以实现它,有些比其他方法更有效。我们希望利用这些机会对我们有利。
它们可以是程序中的各种正交属性。阅读这篇博客文章以获取更多插图。这一个稍微讨论了编程中组件的差异,例如线程。
请注意,线程或多任务处理都是服务于更具体目的的计算实现。它们可能与并行和并发有关,但不是本质上的。因此,它们不是开始解释的好条目。
还有一个亮点:(物理)“时间”和这里讨论的属性几乎没有任何关系。时间只是为了展示属性的意义而将度量实现的一种方式,但远不是本质。请三思时间复杂度中“时间”的作用——两者或多或少是相似的,在这种情况下甚至度量往往更重要。
并行是在multiple cores per CPU或multiple CPUs (on a single motherboard)上同时执行进程。
multiple cores per CPU
multiple CPUs (on a single motherboard)
并发是通过使用调度算法划分CPU的时间(时间片)在single core/CPU上实现并行。进程是交错。
single core/CPU
单位: 单个CPU中的1个或多个内核(几乎所有现代处理器) 主板上有1个或多个CPU(想想老式服务器) 1个应用程序是1个程序(Chrome浏览器)1个程序可以有1个或多个进程(认为每个Chrome浏览器选项卡都是一个进程)1个进程可以有1个或多个线程来自1个程序(Chrome标签在1个线程中播放YouTube视频,另一个线程产生评论部分,另一个用于用户登录信息)因此,一个程序可以有一个或多个执行线程1进程是thread(s)+allocated memory resources by OS(堆、寄存器、堆栈、类内存)
单位:
thread(s)+allocated memory resources by OS
并发编程执行有两种类型:非并行并发编程和并行并发编程(也称为并行)。
关键的区别在于,在人眼看来,非并行并发的线程似乎同时运行,但实际上它们没有。在非并行并发线程中,通过时间切片快速切换并轮流使用处理器。虽然并行有多个处理器可用,但多个线程可以同时在不同的处理器上运行。
参考:编程语言中的并发简介
“并发”是指同时做任何事情。它们可能是不同的事情,也可能是同一件事。尽管缺乏公认的答案,但这并不是“似乎在同一时间”。它实际上是在同一时间。你需要多个CPU内核,要么使用一台主机内的共享内存,要么使用不同主机上的分布式内存,来运行并发代码。同时并发运行的3个不同任务的管道就是一个例子:任务级别2必须等待任务级别1完成的工作单元,任务级别3必须等待任务级别2完成的工作单元。另一个例子是1-生产者与1-消费者的并发;或多生产者和1-消费者;读者和作家;等。
“并行”是同时做同样的事情。它是并发的,但更重要的是,它是同时发生的相同行为,最典型的是在不同的数据上。矩阵代数通常可以并行化,因为你有相同的操作重复运行:例如,矩阵的列和可以使用相同的行为(sum)但在不同的列上同时计算。在可用的处理器内核之间分区(拆分)列是一种常见的策略,这样每个处理器内核处理的工作量(列数)接近相同。另一种拆分工作的方法是任务包,完成工作的员工回到经理那里,经理会分发工作,动态地获得更多的工作,直到一切都完成。票务算法是另一种。
不仅仅是数字代码可以并行化。文件经常可以并行处理。在自然语言处理应用程序中,对于数百万个文档文件中的每一个,您可能需要计算文档中的标记数量。这是并行的,因为您正在计算每个文件的标记,这是相同的行为。
换句话说,并行是指同时执行相同的行为。并发意味着同时,但不一定是相同的行为。并行是一种特殊的并发,其中同样的事情同时发生。
例如,术语将包括原子指令、临界区、互斥、旋转等待、信号量、监视器、屏障、消息传递、map-duce、心跳、环、票务算法、线程、MPI、OpenMP。
Gregory Andrews的工作是这方面的顶级教科书:多线程、并行和分布式编程。
摘自这个惊人的博客:
并发和并行的区别: 并发是指两个任务可以在并行是指任务实际运行在同时,例如。在多核处理器上。 并发是独立执行的进程的组合,并行是同时执行(可能相关)计算。 并发一次大约是处理很多事情。并行同时做很多事情. 应用程序可以是并发的,但不能是并行的,这意味着它同时处理多个任务,但没有两个任务在同一时间执行。 应用程序可以是并行的,但不能是并发的,这意味着它同时在多核CPU中处理一个任务的多个子任务时间 应用程序既不能并行也不能并发,这意味着它一次一个顺序地处理所有任务。 应用程序既可以是并行的,也可以是并发的,这意味着它同时在多核CPU中处理多个任务时间
并发和并行的区别:
并发是指两个任务可以在并行是指任务实际运行在同时,例如。在多核处理器上。
并发是独立执行的进程的组合,并行是同时执行(可能相关)计算。
并发一次大约是处理很多事情。并行同时做很多事情.
应用程序可以是并发的,但不能是并行的,这意味着它同时处理多个任务,但没有两个任务在同一时间执行。
应用程序可以是并行的,但不能是并发的,这意味着它同时在多核CPU中处理一个任务的多个子任务时间
应用程序既不能并行也不能并发,这意味着它一次一个顺序地处理所有任务。
应用程序既可以是并行的,也可以是并发的,这意味着它同时在多核CPU中处理多个任务时间
简单地说,并发是同时处理很多事情。
“处理”一词用粗体显示了并发和并行之间的区别。一次处理许多事情意味着一次完成许多事情,但它们是否在同一时间执行并不重要。另一方面,做并行意味着同时做很多事情(同时执行)。因此,并发上下文可以用一个或多个处理资源实现。用一个处理资源一次处理许多事情意味着你在任务之间做上下文切换,在同一时间执行许多事情。另一方面,具有许多处理资源的并发上下文意味着做并行。这意味着我们通过并行来实现并发,而不是相反。
您可能想在我的文章中了解更多关于并发和并行以及它们与当今技术的关系。
只是为了进一步澄清其他好答案:
基于处理的抽象(CPU是一个可以想象的例子)能够在同一时刻运行唯一的任务的前提,
并发是一个关于处理非常抽象的故事:它可以在不同的任务之间切换。
并行是一个关于我们有不止一个处理抽象的故事(例如我们的CPU有多个内核)。所以它是我们系统能够同时执行多个任务的原因(字面上)。但是这里没有提到处理的特定抽象(它们是否并发)。
这里的重点是什么这些故事。
所以当你阅读接受的答案时要注意:
并发是指两个或多个任务可以在时间重叠
严格来说,可以根据该定义得出结论,并行性本身就是以并发为前提的。
订阅关于Robert Love的评论:
并发、并行和竞赛线程创建两个相关但不同的现象:并发和并行性。两者都是苦乐参半,触及线程的成本并发是两个或两个以上的能力要在重叠时间时期.并行中执行的线程执行两个或多个线程同时的能力。并发可以在没有并行的情况下发生:例如,多任务处理并行(有时强调为真并行)是一种特定形式的并发,需要多个处理器(或能够使用多个引擎的单个处理器)的执行,例如GPU)。通过并发,多个线程可以向前推进,但不一定同时进行并行性,线程实际上并行执行,允许多线程程序使用多个处理器。并发是一种编程模式,一种处理问题的方式。并行是一种硬件特性,可以通过并发实现。两者都很有用
线程创建两个相关但不同的现象:并发和并行性。两者都是苦乐参半,触及线程的成本并发是两个或两个以上的能力要在重叠时间时期.并行中执行的线程执行两个或多个线程同时的能力。并发可以在没有并行的情况下发生:例如,多任务处理并行(有时强调为真并行)是一种特定形式的并发,需要多个处理器(或能够使用多个引擎的单个处理器)的执行,例如GPU)。通过并发,多个线程可以向前推进,但不一定同时进行并行性,线程实际上并行执行,允许多线程程序使用多个处理器。
并发是一种编程模式,一种处理问题的方式。并行是一种硬件特性,可以通过并发实现。两者都很有用
这个解释与公认的答案是一致的。实际上这些概念比我们想象的要简单得多。不要认为它们是魔法。并发大约是一段时间,而并行大约是与此同时,同时。
并发与并行
Rob Pike在“并发不是并行”
并发是指同时处理很多事情。
并行是指同时做很多事情。
[并发理论]
并发-一次处理多个任务并行-一次处理多个线程
我对并发和并行的看法
[同步vs异步]
如果你想向一个9岁的孩子解释这一点。
我认为在这个问题上有两个不同的观点造成了混乱:程序员的观点(并发/并行编程)vs从计算机/操作系统的角度来看(并发/并行执行)。
从计算机的角度来看回答这里。
程序员的观点:
并行编程:程序员在编写代码时知道代码将由多个线程执行,无论出于什么原因。原因可能是:在等待I/O时更好地利用CPU,由不同线程处理Web请求,通过在与主线程分开的线程中运行计算使GUI响应,运行周期性的后台任务。程序员必须应用互斥结构,锁定/解锁,等待条件/信令,处理死锁等,多个线程可以在单个处理器/内核上运行(从计算机的角度来看是并发的),也可以在多个内核上运行(从计算机的角度来看是并行的)。
并行编程:程序员知道程序将在具有多个处理器/内核的计算机上运行,并且想要利用多核。程序员将CPU密集型计算划分为多个子任务,在一个线程中运行每个子任务,一旦线程完成,它们的结果将组合成总结果(分而治之)。例如,将一些矩阵处理代码划分为并行处理矩阵部分的任务。每个核心将一个线程执行一个子任务(或者多个线程同时执行,如果线程数大于内核数)。程序员也必须在这里应用并发的编程构造,但她也关心将任务划分为子任务并组合结果。例如,在Java,程序员可以使用ParallelStreams,它将自动拆分数据并组合结果。如果程序员知道程序将在单核处理器上执行,那么将CPU密集型任务拆分为多个线程没有好处。从Java中的并发编程:设计原则和模式,第2版,1999年,Doug Leah,第343页:
并行程序专门设计用于利用多个CPU来解决计算密集型问题。