并发(Concurrency)和并行(Parallelism)的区别

最近在读《real world haskell》里关于并行的一章时,看到作者首先对并发(Concurrency)和并行(Parallelism)的区别进行了定义和解释。以前我对这个问题也是一知半解,如果有人问题这个问题,恐怕我只能挠头说不清楚。而在这本书里,作者的解释是(简单翻译):

一个并发程序是指能同时执行通常不相关的各种任务。以一个游戏服务器为例子:它通常是有各种组件组成,每种组件都跟外部世界进行着复杂的信息交互。一个组件有可能要处理多个用户聊聊;另外一些可能要处理用户的输入,并把最新状态反馈给用户;其它的用来进行物理计算。这些都是并发处理。

并发程序并不需要多核处理器。

相比之下,并行程序是用来解决一个单一任务的。以一个试图预估某支股票价格在下一分钟波动情况的金融组件为例,如果想最快速度的知道标普500中哪知股票应该卖出还是买进,你不能一个一个的计算,而是将这些所有的股票同时计算。这是并行。

其实也不是很好懂,我自己琢磨了一下,大概是这个道理:并发就是一心二用(多用),比如你一边听老师讲课,一边低头看课桌下韩寒的小说。这两件事你在同时做,而且这两件事并不一定需要相关。而并行就是兵分几路干同一个事情。比如别人看小说只能一行一行的看,而你能一目十行,这就是并行。:) 。

关于并发和并行的区别,Go语言有一个非常好的教材,叫做“并发不是并行”,它以Go语言为例,图文并茂的为我们讲解了并发和并行之间的联系和区别。

并发不是并行

文中使用地鼠烧书为例,通过设计出不同的并发装书、运书、烧书的流程来比较并发和并行技术的组合运用。原文是英文的,这里是外刊IT评论网翻译的中文版并发不是并行,供大家欣赏。(提示:这个教材使用HTML5技术做成了幻灯片的形式,所以你需要使用支持HTML5的现代浏览器浏览。)

并发不是并行

分享这篇文章:

16 Responses to 并发(Concurrency)和并行(Parallelism)的区别

  1. 优优网事 says:

    并行:是严格的同时执行,而并发并不是严格的同时执行,而是以时间片为单位交替执行,所以不需要多处理器。

    举个例子:
    A和B需要各自挖一个坑,各自挖好需要时间10分钟。那么并行,就是同时执行,10分钟后,两个大坑就挖好了。而并发(单核),则20分钟后,两个坑才挖好。因为A和B是交替执行的。这一秒A挖,下一秒B挖,,,,,如此交替下去。。。。

  2. Gerry says:

    上面的图,没区别啊~~

  3. Terry says:

    只能说,你举的例子更烂。边听课边看小说就是并发?一目10行就是并行啊?拜托别出来误导大众好不好!

  4. 铁锚 says:

    按照文章理解,并发就是多个不相关任务,同时(在不同的线程/进程)里执行。
    并行,就是(逻辑上的)同一个任务,分成多个小块,同时在多个CPU/线程/进程 里面执行.
    我觉得区别在于 是不是同一个任务的拆分。

  5. oceannut says:

    并发:若干个人(一个或多个),做若干件事情(一个或以上),各做各的,各有各的结果,没有必然的互相影响。并行,若干个人(要求多个),做一件事情(根据人数合理拆分任务),也是各做各的,但是最终结果要合并,所以每个人完成任务的速度、质量等都会影响最终的结果。

  6. 123 says:

    为了便于理解,这里的任务(对人来说)假设为一整件事情,而同一任务中不同部分划分叫做片段(对机器来说)。做个不恰当的类比:程序和进程。
    以单线程单核为例:
    并发需要调度器轮询的执行多个片段,每个片段之间没有彼此关联(例如一个片段等待另一个片段的数据输入);
    多核时,并行可以将一个任务放到其他的cpu或内核中同时的执行;
    例如要给10个客人准备10杯茶,相当于每个客人1杯茶这件事(任务)去重复做10次,那么这个任务可以并行;
    而为每个客人准备1杯茶这件事情又可以分为:拿杯子、烧水、取茶叶、冲茶、奉茶,其中拿杯子(5个片段),烧水,取茶叶(其中3个不相关的片段)又是可以同时(或者说交替轮询)去做的,所以又可以并发。
    假如每一个动作耗时1s,那么通过并发+并行这个任务的执行时间可以由原来的50s降低到3s。

    • 123 says:

      纠错:而为每个客人准备1杯茶这件事情又可以分为:拿杯子、烧水、取茶叶、冲茶、奉茶,其中拿杯子(5个片段),
      【改为】::而为每个客人准备1杯茶这件事情又可以分为:拿杯子、烧水、取茶叶、冲茶、奉茶(一共5个片段),其中拿杯子,

  7. 抓狂 says:

    并发和并行,其关键在于其关注点不同。

    并发关注的是资源充分利用;比如你(代表资源)在公司打工,老板为了最大化压榨你,会给你各种活儿干(代表任务),让你别闲下来;这时候你是在并发工作的,但你不可能同时做两个活儿,只能一个一个的干(早期的批处理系统),或者把每个活儿分解成一个一个关联度不高的小活儿,交替着干(现代的分时系统)

    并行关注的是一个任务被分解给多个执行者同时做,缩短这个任务的完成时间;比如你们老板接了个大活儿,把这个大活儿拆分成多个尽量不相干的小活分给多个人干;这里重点是“尽量不相干”,如果老板牛、拆得好,多个人不需要沟通很快就做完了,如果老板烂、拆得差,多个人需要频繁沟通等待别人,那就会非常慢,有可能比一个人做还慢,这里在员工水平一致的情况下(代表并行需要的资源),老板的水平(并行算法)决定了任务的快慢。

    进一步,并发和并行是可以组合的,比如你给多家公司兼职,就相当于你在”并发“的(针对你而言是并发)干活,而你干的活儿是在”并行“着(还有其它人在干)

    • Liigo says:

      “会给你各种活儿干……这时候你是在并发工作的,但你不可能同时做两个活儿”,如果干活的“你”代表CPU,那么在多核环境中,就不止一个“你”了,他们是可以“同时干活”的。所有我感觉你这里的陈述把并发理解成了“单核时代的并发”。

  8. Leonardo.Z says:

    第7张slide上的错误:包括Erlang等其它语言都是基于这种SCP模式

    1 CSP被错打成了SCP。 2 Erlang 并不是基于CSP,而是基于Actor Model

  9. Liigo says:

    本人(Liigo)的理解:从高端大气上档次的角度说,低端 << 串行 << 并发 << 并行 << 高端,即并发是串行的高级阶段,并行又是并发的高级阶段。串行就是做一件事严格按照先后顺序依次完成,就算在单核CPU环境中都是低效的,在多核环境中就更加低效了。并发就是把一件事分成多个相对独立的子单元,各子单元互不干扰的同时执行(或寻找间隙执行),这样,即使是单核环境下也是高效的,多核环境下更加高效。并行就是拿出N个CPU并发执行一件事,再拿出另外的N个CPU并发执行另外的一件事,这几件事互不干扰的同时执行,可以粗略地理解为并发地执行并发任务。从系统设计难度的角度说,串行最容易,并发很困难,并行更加困难。

    下面做一些解释:
    为什么串行在单核环境中也是低效的?因为电脑在执行一件任务时通常不是时时刻刻占满CPU资源,很多时候因磁盘延迟、网络延迟做无意义的等待,这些时间CPU是空闲的、浪费的。
    为什么并发在单核环境中也是高效的?通过拆分子任务,将一些不需要严格按照先后顺序执行的子任务,安排在CPU空闲时执行,最终效果是压缩了CPU空闲的时间,加速了任务完成。
    为什么并发、并行的设计难度很大?需要拆分子任务,需要分析子任务之间的逻辑关系,需要处理系统中的并发瓶颈,……所有这些都需要深度思考。比按部就班的串行执行要复杂的多。
    为什么要并发、并行?现在都是多核CPU+多核GPU时代了,浪费系统运算资源就是犯罪呀,况且要执行的任务多是涉及大数据、云计算,想不并发、并行都难啊。

  10. 大灰狼 says:

    和舍友讨论的结果:一个CPU可以“并发”执行多个任务,但谈不上“并行”,因为就一个执行者(CPU)。 多个这样的CPU,则可以“并行”地工作了,即同时可以做“并发”工作。

  11. brian 对这篇文章的反应是俺的神呀
  12. 周明宏 对这篇文章的反应是赞一个
  13. 3 对这篇文章的反应是标题党

发表评论

电子邮件地址不会被公开。 必填项已用*标注