并发介绍

Golang是一种并发(concurrent)编程语言,但不是并行(parallel)编程语言。在讨论并发编程之前我们先弄明白并发与并行的区别。

并发及其两种实现(任务切换 & 多核并行)

并发是指在一段时间内能同时完成多个任务。

举个例子,比如晨练跑步,一个跑步的过程中发现了鞋带送了,可以暂时停下来系鞋带,然后接着跑步。这就是一种并发,因为系鞋带并未打断跑步的进行,只是暂停了一下而已。

再举个例子,还比如晨练跑步,一个人可以边跑步边听音乐,这是同时互不打断的执行的,也是一种并发。

细心点我们就能总结出来区别,第一种并发需要暂停一个任务,转而去执行另外一个任务,然后再回来接着执行刚才的任务。这种并发实现方式叫做任务切换。而后一种是同时执行多个任务,对应到计算机里面就是需要有多个CPU核心来分别控制,因此属于真正的多核并行

因此我们可以这么理解并发并行的关系:并行只是一种实现并发的关系,另外一种实现并发的方式是任务切换

这里有一个非常好的问答解释了二者的区别,大家可以看一下。

再举个更加真实的例子,比如我们常用的浏览器可以渲染页面,也可以下载文件,这两个不同的任务就是并发的,但是实现上可以采用任务切换也可以基于多个CPU采用多核并行

  • 任务切换

  • 多核并行

操作系统级别&编程语言级别的抽象

现在的计算机基本上都是多核CPU,所以多个任务的执行完全有可能是并行执行的。但是计算机同时执行的任务可以多达几十个甚至上百个。因此操作系统级别提供了一种抽象,线程,来方便我们实现并发编程,可以并发执行非常多的任务,而具体如何调度各个线程的执行则是操作系统需要关注的事。因此在我们的应用开发中只需要关注线程级别的并发即可,具体多个线程是跑在单核还是多核上则无需关系。对于这个层面的知识体系推荐大家阅读<>。

出了操作系统级别的抽象之外,我们在应用程序或者服务端程序开发时一般是基于某个流行的编程语言,一般编程语言又会提供各种各样的抽象,比如Java中的线程,Golang中的Goroutines(协程)等等。当然,虽然不同编程语言对于并发编程都有自己的封装抽象,但是易用性却相差较大,Golang现在非常流行的其中一个重要原因就是Goroutines(协程)的方便易用,后面几节我们具体介绍。

Last updated