前段时间在公司给大家分享GO语言的一些特性,然后讲到了并发概念,大家表示很迷茫,然后分享过程中我拿来了Rob Pike大神的Slides 《Concurrency is not Parallelism》,反而搞的大家更迷茫了,看来大家丢了很多以前的基本知识。后来我就把Pike大神的slide和网上的一些牛人关于Cocurrency和Parallelism的观点做了整理,最终写了本文。

在Rob Pike的《Concurrency is not Parallelism》(http://talks.golang.org/2012/waza.slide)中说到,我们的世界是Parallelism,比如网络,比如大量独立的个人。但是需要协作的。所以就有了并发。很多人认为并发很COOL,认为并发就是并行。但是这种观念在ROB PIKE看来是错误的。比如之前有个人写了一个质数筛选的程序,然后这个运行在4核的平台上,但是运行结果很慢。这个程序员错误的以为GO提供的并发就是并行计算。

在Rob的这个slide中举了一个地鼠烧书的例子,在我和小伙伴们一起看的时候表示不太理解,所以做了一些功课来理解。

为了更容易的搞懂Rob提的并发不是并行的概念,就需要搞懂并发和并行到底有什么区别。

在Rob看来,Concurrency是一种把一些独立的执行过程组合起来的程序设计方法。

而Parallelism是同时执行一些可能相关(结果相关而不是依赖耦合关系的相关)或者独立计算过程。

Rob总结到:

Concurrency is about dealing with lots of things at one.

Parallelism is about doing lots of things at one. Not the same, but related.

Concurrency is about structure, parallelism is about execution.

Concurrency provides a way to structure a solution to solve a problem that may(but not necessarily) be parallelizable.

Rob还提到:

Concurrency is a way to structure a program by breaking it into pieces that can be executed independently.

Communication is the means to coordinate the independent executions.

This is the GO model and it's based on CSP.

上面的只有一只地鼠推着小车把一堆语言手册运送到焚烧炉中烧掉。如果手册很多,运送距离很远,那么整个过程就要花费很多时间。

然后增加一只地鼠来一起帮忙做这个事情,但是两个人来做,只有一辆小推车是不够的,所以需要更多的车子

虽然车子增加了,但是有可能手册不够少了,或者炉子不够用了,而且两只地鼠需要做工作的时候协商搬书到车里,或者协商谁先用炉子。工作效率也不是太高。

因此我们把它们真正的独立开。它们之间就不需要协商了,也都有足够的手册可以烧了。

虽然上面两只地鼠都分开独立的运行了,但是它们之间有并发成分(Concurrent composition)存在。

假设在一个单位时间内,只有一只地鼠在工作,它们就不是并行(Parallel),它们还是并发的。

这个设计不是为了有意并行而设计,但是可以自然地转化为可并行的(The design is not automatically parallel. However, it's automatically parallelizable)。

而且这个并发成分还暗示了有其他的模型。

这里三只地鼠活动,可能有些延迟。每个地鼠都是一个独立的执行过程。它们协作交流。

这里新增加了一只地鼠用于推送空车子到装书处。每只地鼠都只做一件事情。这个并发的粒度比以前的更细小了。

如果我们把一切正确的安排好(虽然可能令人难以置信,但是并非不可能),这个设计会比最开始的那一只地鼠的效率要快4倍。

我们在原有的设计里增加了一个并发的执行过程提升了性能。

Different concurrent designs enable different ways to parallelize.

这种并发的设计可以很容易的使这个流程并行的执行。比如下面这样:8只地鼠繁忙的工作。

需要记住的是,即使在单位时间内只有一只地鼠在活动,此时虽然不是并行的,但是这个设计还是一个正确的并发的解决方案。

还有另外一种结构来组织两只地鼠的并发因素.即在两只地鼠中间再增加一堆手册。


然后我们可以也很容易的并行执行:

还有一个组织方式:

然后再并行它:

现在有16只地鼠在工作了!

有很多方式可以分解一个过程。这个分解的过程就是并发的设计。一旦我们做好分解,并行化和正确性就会变的容易。
There are many ways to break the processing down. That's concurrent design. Once we have the breakdown, parallelization can fall out and correctness is easy.

一个复杂的问题可以分解为多个可以简单易懂的部分,然后把它们并发地(concurrently)组合在一起。最后得到一个简单易懂,高效的,可伸缩的而且正确的设计。甚至可以并行。

并发是非常强大的,虽然不是并行,但是可以做到并行,而且可以容易的做到并行,甚至是可伸缩性或者其他任何的东西。

把上面地鼠的例子转换到我们计算机中,书堆就好比网页内容,地鼠好比CPU,小推车好比序列化器或者渲染过程,或者网络,而火炉就是最终的消费者,比如浏览器。

就是说浏览器发起请求,地鼠开始工作,把需要的网页内容渲染好,然后通过网络再发回浏览器。这也就变成了一个针对可伸缩的WEB服务做的并发的设计。

在Golang中,Goroutine就是一个与其他goroutine在同一地址空间但是是独立执行的函数。Goroutine不是线程,虽然有点像,但是比线程更轻量。

Goroutine会被多路复用到需要的系统线程中。当一个goroutine阻塞了,其相关的线程也阻塞了,但是其他的goroutine没有阻塞(注:这种阻塞是指一些系统调用,而像网络操作,CHANNEL操作之类的,goroutine会被放入等待队列中,等运行条件成立,比如网络操作完毕,或者从CHANNEL中处理好收发,那么就会被切换到运行队列中运行)

Golang还提供了Channel用于goroutine之间的同步和数据交换。Select语句类似于switch,只是是用于判断哪个channel可以通信。

Golang是真的支持并发,一个Golang可以创建非常多的goroutine,比如一个测试程序创建了130W个goroutine,而且每个goroutine的栈开始的时候都比较小,但是会需扩大或收缩。但是Goroutine不是免费的,但是是轻量的。


总结


用于区别Concurrency和Parallelism的最好的例子是哲学家进餐问题。经典哲学家进餐问题中,如果刀或者叉不够的时候,每个哲学家就需要协商来确保总有一个人能够吃到饭。而如果餐具足够了,那么就需要协商了,大家可以很嗨皮的各吃各的了。

Concurrency与Parallelism最大的区别是要满足Concurrency,每个独立的执行体之间必须有协作,协作工具比如锁或者信号量,或者队列。

而Parallelism虽然也有很多独立的执行体,但是它们不是需要协作的,只需要自己运行,计算出结果,最后被汇总起来就好了。

Concurrency是一种问题分解和组织方法,而Parallelism一种执行方式。两者不同,但是有一定的关系。

我们大部分的问题都可以切割成细小的问题,每个问题作为一个独立的执行体执行,相互间有协作,它们就是Concurrency。

这种设计方式并不是为了Parallelism,但是这种设计可以自然而然的转化为可并行的。而且这种设计方式还能够确保正确性。

Concurrency不管是单核机器还是多核机器,还是网络或者其他平台,都具有更好的伸缩性;

而Parallelism在单核机器上就做不到真正的Parallelism。但是Concurrency在多核机器上反而有可能自然而然的进化为Parallelism。

Concurrency的系统的结果是不确定的(indeterminate),为了保证确定性,需要用锁或者其他方式解决。而Parallelism的结果是确定的。

Golang是支持并发的,可以做到并行的执行Goroutine(即通过runtime.GOMAXPROC设置P的数量)。基于CSP提供了Goroutine,channel和select语句,提倡大家通过Message-Passing进行协作,而不是通过锁等工具。这种协作方式可以带来更好的可扩展性。


在维基百科中,关于Concurrent的定义如下:

Concurrent computing is a form of computing in which several computations are executing during overlapping time periods – concurrently – instead of sequentially (one completing before the next starts). This is a property of a system – this may be an individual program, a computer, or a network – and there is a separate execution point or "thread of control" for each computation ("process"). A concurrent system is one where a computation can make progress without waiting for all other computations to complete – where more than one computation can make progress at "the same time"

Concurrent computing is related to but distinct from parallel computing, though these concepts are frequently confused, and both can be described as "multiple processes executing at the same time". In parallel computing, execution literally occurs at the same instant, for example on separate processors of a multi-processor machine – parallel computing is impossible on a (single-core) single processor, as only one computation can occur at any instant (during any single clock cycle).(This is discounting parallelism internal to a processor core, such as pipelining or vectorized instructions. A single-core, single-processor machine may be capable of some parallelism, such as with a coprocessor, but the processor itself is not.) By contrast, concurrent computing consists of process lifetimes overlapping, but execution need not happen at the same instant.

For example, concurrent processes can be executed on a single core by interleaving the execution steps of each process via time slices: only one process runs at a time, and if it does not complete during its time slice, it is paused, another process begins or resumes, and then later the original process is resumed. In this way multiple processes are part-way through execution at a single instant, but only one process is being executed at that instant.

Concurrent computations may be executed in parallel, for example by assigning each process to a separate processor or processor core, or distributing a computation across a network. This is known as task parallelism, and this type of parallel computing is a form of concurrent computing.

The exact timing of when tasks in a concurrent system are executed depend on the scheduling, and tasks need not always be executed concurrently. For example, given two tasks, T1 and T2:

  • T1 may be executed and finished before T2
  • T2 may be executed and finished before T1
  • T1 and T2 may be executed alternatively (time-slicing)
  • T1 and T2 may be executed simultaneously at the same instant of time (parallelism)

The word "sequential" is used as an antonym for both "concurrent" and "parallel"; when these are explicitly distinguished, concurrent/sequential and parallel/serial are used as opposing pairs

Concurrency的定义如下:

In computer science, concurrency is a property of systems in which several computations are executing simultaneously, and potentially interacting with each other.

The computations may be executing on multiple cores in the same chip, preemptively time-shared threads on the same processor, or executed on physically separated processors.

A number of mathematical models have been developed for general concurrent computation including Petri nets,process calculi, the Parallel Random Access Machine model, the Actor model and the Reo Coordination Language.

Because computations in a concurrent system can interact with each other while they are executing, the number of possible execution paths in the system can be extremely large, and the resulting outcome can be indeterminate. Concurrent use of shared resources can be a source of indeterminacy leading to issues such as deadlock, and starvation.

The design of concurrent systems often entails finding reliable techniques for coordinating their execution, data exchange, memory allocation, and execution scheduling to minimize response time and maximize throughput.

关于Parallelism的定义如下:

Parallel computing is a form of computation in which many calculations are carried out simultaneously,

operating on the principle that large problems can often be divided into smaller ones, which are then solved concurrently (“in parallel”).

By contrast, parallel computing by data parallelism may or may not be concurrent computing – a single process may control all computations, in which case it is not concurrent, or the computations may be spread across several processes, in which case this is concurrent. For example, SIMD (single instruction, multiple data) processing is (data) parallel but not concurrent – multiple computations are happening at the same instant (in parallel), but there is only a single process. Examples of this include vector processors and graphics processing units (GPUs). By contrast, MIMD (multiple instruction, multiple data) processing is both data parallel and task parallel, and is concurrent; this is commonly implemented as SPMD (single program, multiple data), where multiple programs execute concurrently and in parallel on different data.

Concurrency有Parallelism所不具备的特性:interacting。并发的程序中,每个执行体之间都是可以相互作用的。

Concurrency != Parallelism的更多相关文章

  1. What is the difference between concurrency, parallelism and asynchronous methods?

    Ref: http://stackoverflow.com/questions/4844637/what-is-the-difference-between-concurrency-paralleli ...

  2. Concurrency vs. Parallelism

    http://getakka.net/docs/concepts/terminology Terminology and Concepts In this chapter we attempt to ...

  3. GCD 使用若干注意事项

    这篇文章写的是看完 WWDC 17 - Modernizing GCD Usage 之后的笔记. 一.Parallelism & Concurrency Parallelism 指的是在多个 ...

  4. 一 Akka学习 - actor

    (引用 http://shiyanjun.cn/archives/1168.html) 一: 什么是Akka? Akka是JAVA虚拟机JVM平台上构建高并发.分布式和容错应用的工具包和运行时,是一个 ...

  5. Java高并发-概念

    一.为什么需要并行 业务要求 http处理多个客户端请求 java虚拟机启动多个线程 进程开销比线程大的多 性能 多线程在多核系统比单线程要好的多 摩尔定律失效 二.几个重要概念 2.1 同步和异步 ...

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

    最近在读<real world haskell>里关于并行的一章时,看到作者首先对并发(Concurrency)和并行(Parallelism)的区别进行了定义和解释.以前我对这个问题也是 ...

  7. Concurrency Is Not Parallelism (Rob pike)

    Rob pike发表过一个有名的演讲<Concurrency is not parallelism>(https://blog.golang.org/concurrency-is-not- ...

  8. 并行(Parallelism)与并发(Concurrency)

    并行(Parallelism):多任务在同一时刻运行.例如,多个任务在多核处理器上运行. 并发(Concurrency):两个或者两个以上的任务在一段时间内开始.运行.完成,这意味着它们不是在同一时刻 ...

  9. Parallelism VS Concurrency

     一个电脑/手机 有很多核,每一个核上运行一个任务,叫做 Parallelism. 只有一个核,通过任务调度,也可以实现 Concurrency.

随机推荐

  1. 实例操作JSONP原理

    絮语:按这个步骤走,你就会明白JSONP是什么鬼. 1.工程目录: ng-mywork demo.html test.js 2.nginx的server配置 server { listen ; ser ...

  2. Electron使用与学习--(页面间的通信)

    目录结构: index.js是主进程js. const electron = require('electron') const app = electron.app const BrowserWin ...

  3. ASP.NET Core应用中如何记录和查看日志

    日志记录不仅对于我们开发的应用,还是对于ASP.NET Core框架功能都是一项非常重要的功能特性.我们知道ASP.NET Core使用的是一个极具扩展性的日志系统,该系统由Logger.Logger ...

  4. javascript中的继承与深度拷贝

    前言 本篇适合前端新人,下面开始...... 对于前端新手来说(比如博主),每当对js的对象做操作时,都是一种痛苦,原因就是在于对象的赋值是引用的传递,并非值的传递,虽然看上去后者赋值给了前者,他们就 ...

  5. .NET跨平台之运行与Linux上的Jexus服务器

    谈及.NET跨平台,已经不是什么稀奇的事儿.今天我们就以Jexus服务器的部署为例.简单示范下.在这里,我用VMWare虚拟机来搭建Linux运行环境. Linux,我们选择CentOS7.大家可以前 ...

  6. CSS 3 学习——渐变

    通过CSS渐变创建的是一个没有固定比例和固定尺寸的<image>类型,也就是说是一张图片,这张图片的尺寸由所应用的元素的相关信息决定.凡是支持图片类型的CSS属性都可以设置渐变,而支持颜色 ...

  7. Java多态性——分派

    一.基本概念 Java是一门面向对象的程序设计语言,因为Java具备面向对象的三个基本特征:封装.继承和多态.这三个特征并不是各自独立的,从一定角度上看,封装和继承几乎都是为多态而准备的.多态性主要体 ...

  8. ExecuteOrDelayUntilScriptLoaded 还是 SP.SOD.executeFunc?

    SharePoint 客户端 JS 开发时,要等待 SharePoint 对象都加载完毕再调用自己的方法(myFunction),可以有两种方式: ExecuteOrDelayUntilScriptL ...

  9. SQL Server2014 SP2关键特性

    SQL Server2014 SP2关键特性 转载自:https://blogs.msdn.microsoft.com/sqlreleaseservices/sql-2014-service-pack ...

  10. 深入浅出聊优化:从Draw Calls到GC

    前言: 刚开始写这篇文章的时候选了一个很土的题目...<Unity3D优化全解析>.因为这是一篇临时起意才写的文章,而且陈述的都是既有的事实,因而给自己“文(dou)学(bi)”加工留下的 ...