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


当前回答

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

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


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

并发:至少有两个线程正在进行时存在的条件。一种更为普遍的并行形式,可以将时间切片作为虚拟并行的一种形式。并行性:当至少两个线程同时执行时出现的情况。

其他回答

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

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

只是为了给其他好答案添加更多的澄清:

基于处理的抽象(CPU作为一个完全可以想象的例子)能够在同一时刻运行唯一的任务的前提,

并发是一个关于处理抽象的故事:它可以在不同的任务之间切换。

并行是一个关于我们有多个处理抽象的故事(例如,我们的CPU有多个内核)。因此,这是我们的系统能够同时执行多个任务的原因(字面意思)。但这里没有提到处理的特定抽象(它们是否并发)。

这里的重点是这些故事的内容。

因此,当您阅读公认答案时,请注意:

并发是指两个或多个任务可以在重叠的时间段。

严格地说,我们可以根据这个定义得出结论,并行性本身就是并发性的前提。

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

假设一个组织组织了一场国际象棋比赛,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-campion+10xtransition_time=2分钟)

假设所有玩家都需要45秒才能完成他们的回合,那么根据SERIAL事件的每场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名选手同时比赛(读第二分),因此现在跨组的比赛是并行运行的,但在组内,他们是同时运行的。

因此,一组游戏将在11xtime_per_turn_by-playerer_&_champion+1extransition_time_across_5_layers=11x51+11x30=600+330=930秒=15.5分钟(大约)内完成

因此,整个活动(包括两个这样的平行跑步组)大约将在15.5分钟内完成

看到从101分钟到15.5分钟的改进(最佳方法)

注意:在上述场景中,如果您用10个类似的工作替换10个玩家,用两个CPU核心替换两个职业玩家,则以下顺序仍然正确:

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

(注意:此顺序可能会因其他情况而改变,因为此顺序高度依赖于作业之间的相互依赖性、作业之间的通信需求以及作业之间的转换开销)

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

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

程序员的观点:

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

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

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

同意:具有共享资源潜力的多个执行流

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

视差:将问题分成多个相似的块。

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