并发和并行有什么区别?
并发和并行有什么区别?
并发性是指两个或多个任务可以在重叠的时间段内启动、运行和完成。这并不一定意味着它们将同时运行于同一时刻。例如,在单核机器上进行多任务处理。
并行性是指任务实际上在同一时间内运行,例如,在多核处理器上。
引用Sun 的多线程编程指南:
并发性: 当至少有两个线程正在进展时存在的一种情况。此为更一般形式的并行性,可包括作为虚拟并行性形式的分时。
并行性: 当至少有两个线程同时执行时出现的一种情况。
混淆之所以存在,是因为这两个词的字典意义几乎相同:
然而,在计算机科学和编程中使用它们的方式却有很大的不同。以下是我的解释:
那么我上面的定义是什么意思呢?
我将通过一个现实世界的类比来澄清。假设你需要在一天内完成两个非常重要的任务:
现在,问题是任务1需要你去一个极其官僚的政府办公室,而你必须排队等待4小时才能获得你的护照。与此同时,任务2是你的公司要求完成的,是一项关键任务。两项任务都必须在特定的日期完成。
通常,你会驾车去办理护照,需要2个小时的时间,在排队等候4个小时后,完成任务后又需要两个小时的车程回家,在家里再工作5个小时完成演示文稿。
但是你聪明地提前计划了。你带着笔记本电脑去排队等待,并在等待期间开始编写演示文稿。这样,一旦你回到家,你只需要额外工作1个小时而不是5个小时。
在这种情况下,你完成了两项任务,只是分别完成它们的一部分。你打断了护照任务,在等待排队时开始工作演示文稿。当轮到你的号码时,你打断了演示文稿任务并切换到护照任务。节省的时间主要是由于两个任务的可中断性。
我认为,并发可以被理解为ACID中的“隔离”属性。如果可以在每个子事务中以任何交错的方式执行并且最终结果与按顺序执行两个任务的结果相同,则认为两个数据库事务是隔离的。请记住,对于护照和演示文稿任务,你是唯一的执行者。
现在,因为你是如此聪明的家伙,显然你已经是高层了,你有一个助手。所以,在你开始护照任务之前,你打电话告诉他准备好演示文稿的初稿。你整天都在完成护照任务,回来看你的邮件时,你发现了演示文稿的草稿。他已经做得很不错了,再编辑2个小时,你就最终确定了它。
现在,由于你的助手和你一样聪明,他能够独立地工作,而不需要经常向你询问澄清问题。因此,由于任务的独立性,两个执行者同时执行了这些任务。
还跟上吗?好的...
记得你的护照任务,需要排队等待吗? 既然这是你的护照,你的助手就不能代替你排队等待。因此,护照任务具有可中断性(你可以在排队等待时停止它,并在稍后当你的号码被叫到时恢复它),但没有独立性(你的助手不能代替你的位置排队等待)。
假设政府机构进行安全检查才能进入场所。在这里,你必须拿出所有电子设备并提交给警察,而他们只有在你完成任务后才会归还你的设备。
在这种情况下,护照任务既不具备独立性也不具备可中断性。即使你在排队等待时,也不能做其他事情,因为你没有必要的设备。
同样,假设演示文稿的性质非常数学化,你需要至少集中100%的注意力5小时。即使你带着笔记本电脑在等待护照任务的队列中,你也无法做到。
在这种情况下,演示文稿任务是独立的(你或你的助手都可以投入5小时的专注工作),但不具有可中断性。
现在,除了将你的助手分配给演示文稿外,你还携带一台笔记本电脑去完成护照任务。在等待排队时,你看到你的助手已经创建了一份共享的幻灯片前10页。你对他的工作进行评论并作出一些更正意见。后来,当你回到家时,你只需要15分钟就能完成最终的草稿,而不是原本需要2个小时。
这是可能的,因为演示文稿任务具有独立性(你们两个中的任何一个都可以完成它)和可中断性(你可以停止它并稍后恢复它)。因此,你可以同时执行两个任务,并在演示文稿任务中执行并行操作。
假设政府机构除了过于官僚外,还存在腐败。因此,你可以出示身份证明,进入场所并开始排队等待,贿赂一个警卫和另一个人来保持你在队列中的位置,溜走,在你的号码被叫到之前回来并继续等待。
在这种情况下,你可以同时且并行地执行护照和演示文稿任务。你可以离开,你的助手接替你的位置。你们两个都可以继续工作,等等。
在计算机领域中,以下是每种情况的典型示例:
如果你理解Rob Pike为什么说并发更好,你必须了解原因。你有一个非常长的任务,其中有多个等待时间,在这些等待期间您需要等待一些外部操作,如文件读取、网络下载。在他的讲座中,他只是在说:“只需将此长时间的顺序任务拆分,以便在等待时可以做一些有用的事情。”这就是为什么他谈论具有各种gopher的不同组织。
现在,Go语言的强大之处在于使用go
关键字和通道使此打破变得非常容易。此外,运行时对调度这些goroutine提供了出色的底层支持。
但本质上,并发比并行更好吗?
苹果比橙子更好吗?
假设你有一个包含两个线程的程序。该程序可以以两种方式运行:
Concurrency Concurrency + parallelism
(Single-Core CPU) (Multi-Core CPU)
___ ___ ___
|th1| |th1|th2|
| | | |___|
|___|___ | |___
|th2| |___|th2|
___|___| ___|___|
|th1| |th1|
|___|___ | |___
|th2| | |th2|
在这两种情况下,我们都有并发性,因为我们有多个线程在运行。补充其他人所说的内容:
并发就像一个杂技演员同时抛接很多球一样。不管看起来怎么样,杂技演员每次只能用一只手接/抛一个球。并行是指同时有多个杂技演员同时抛接球。
并发:如果一个单处理器解决两个或多个问题。
并行:如果多个处理器解决一个问题。
想象通过观看视频教程学习一门新的编程语言。您需要暂停视频,将所说的内容应用到代码中,然后继续观看。这就是并发。
现在您是一名专业程序员。您喜欢在编码时听轻松的音乐。这就是并行。
正如安德鲁·格兰德在GoLang博客中所说:
并发是关于同时处理许多事情。并行则是同时进行许多事情。
享受吧。
我将尝试用一个有趣且易于理解的例子来解释。
假设一个组织举办了一场国际象棋锦标赛,其中10名拥有相同棋艺水平的选手将挑战一名职业冠军选手。由于国际象棋是一种1:1的游戏,因此组织者必须以时间有效的方式进行10场比赛,以便尽快完成整个比赛。
以下情况将很容易描述如何进行这10场比赛:
1) 串行 - 职业选手依次与每个人对局,即与一名选手开始并结束游戏,然后再开始下一场比赛,并且他们决定按顺序进行比赛。因此,如果一场比赛需要10分钟才能完成,则10场比赛将需要100分钟,还要假设从一个比赛到另一个比赛的转换需要6秒钟,那么在10场比赛中需要54秒钟(约1分钟)。
因此,整个事件将在101分钟内完成(最糟糕的方法)。
2) 并行 - 职业选手轮流与每个选手一起玩,因此所有10名选手同时进行比赛,但职业选手不会与两个人玩在一起,他会完成自己的回合并进入下一个人的游戏。现假设职业选手需要6秒钟来完成自己的回合,并且两名选手之间的转换时间为6秒钟,因此总转换时间将为1分钟(10x6秒)。因此,在他回到第一个参赛者之前,已经过去了2分钟(10x职业选手每回合所需时间+ 10x转换时间= 2分钟)。
假设所有选手都需要45秒才能完成自己的回合,则根据串行事件中每场比赛需要10分钟的时间,每个游戏结束之前应进行11轮比赛(约)。
所以整个比赛将大约在11x每位玩家和冠军的每回合时间+ 11x跨越10个玩家的过渡时间完成= 11x51 + 11x60秒= 561 + 660 = 1221秒= 20.35分钟(大约)
从101分钟到20.35分钟,见证了明显的改善(更好的方法)
3)并行 - 假设主办方得到了一些额外的资金,因此决定邀请两名职业选手(都同样有能力),并将相同的10名玩家(挑战者)分成两组,每组5人,并将他们分配给两个冠军,即每个组一个。现在,在这两组中至少有两名玩家(每组一个)正在与其各自组的两名职业选手比赛。
但是,在小组内,职业球员将逐个地接受一名球员(即按顺序),因此您可以轻松推断出整个事件将大约需要50.5分钟才能完成,无需任何计算。
从101分钟到50.5分钟,见证了明显的改善(良好的方法)
4)并发+并行 - 在上述情况下,假设两个冠军选手将与其各自组的5名球员同时进行比赛(参见第2点),因此现在组间游戏并行运行,但是在小组内部游戏会同时进行。
因此,一个小组中的比赛将大约在11x每位玩家和冠军的每回合时间+ 11x跨越5个玩家的过渡时间完成= 11x51 + 11x30 = 600 + 330 = 930秒= 15.5分钟(大约)
因此,整个比赛(涉及两个这样并行运行的小组)将大约需要15.5分钟才能完成。
从101分钟到15.5分钟,见证了明显的改善(最佳方法)
注意: 在上述场景中,如果您将10个球员替换为10个类似的工作,并将两名职业球员替换为两个CPU核心,则以下排序仍将保持不变:串行 > 并行 > 并发 > 并发 + 并行
(注意:对于其他情况,此顺序可能会改变,因为这种排序高度取决于作业之间的相互依赖性,作业之间的通信需求和转换开销)
并发编程执行有两种类型:非并行并发编程和并行并发编程(也称为并行性)。
关键的区别在于,对于人眼来说,在非并行并发中,线程似乎同时运行,但实际上并不是这样。在非并行并发中,线程通过时间片轮流快速切换使用处理器。而在并行性中,有多个处理器可用,因此多个线程可以同时在不同的处理器上运行。
参考:编程语言中的并发介绍
并行性是在具有多核 CPU
或单个主板上的多个 CPU
的计算机上同时运行进程。
并发性是指在单个核心/CPU
上通过使用调度算法(时间片)实现并行性。进程会被交错执行。
单位:
- 一个 CPU 中有一个或多个核心(几乎所有现代处理器都有)
- 一个主板上有一个或多个 CPU(类似老式服务器)
- 一个应用程序就是一个程序(如 Chrome 浏览器)
- 一个程序可以有一个或多个进程(如每个 Chrome 浏览器选项卡)
- 一个进程可以有来自同一程序的一个或多个线程(Chrome 选项卡中播放 YouTube 视频的一个线程,评论部分产生的另一个线程,用户登录信息的另一个线程)
- 因此,一个程序可以有一个或多个执行线程
- 一个进程是
线程(s)+操作系统分配的内存资源
(堆、寄存器、栈、类内存)