20、Golang 教程 - 并发简介

Go是一种并发语言,而不是并行语言。在讨论如何在Go中处理并发之前,我们必须首先了解什么是并发以及它与并行的区别。

什么是并发?

并发是同时处理大量事情的能力。最好用一个例子来解释。

假设一个人喜欢慢跑。在他早上的慢跑时,他的鞋带开了。现在他停下来系鞋带,然后继续慢跑。这就是典型的并发。这个人有能力处理慢跑和系鞋带两件事情,也就是说这个人能够同时处理很多事情。

什么是并行,它与并发有什么不同?

并行指的是同时处理多个事情。虽然听起来类似于并发,实际上它们是不同的。

同样是慢跑的例子。这次,我们假设这个人在慢跑同时还一边用他的 iPod 听音乐。这个例子里,这个人在慢跑同时听音乐,也就是说这个人同时做了多件事情。这就是并行。

从技术上看并发和并行

通过现实中的例子我们明白了什么是并行,以及并行与并发的区别。现在让我们从更技术一点的角度来看待他们(谁让我们是极客呢?)。

假设我们在实现一个 Web 浏览器。 Web 浏览器具有很多组件。其中的两个是网页渲染区域和从互联网下载文件的下载器。让我们假设我们已经构建了我们的浏览器代码,使得每个组件都可以独立执行(这可能是使用了 Java 中的线程,也可能使用了 Go 中的协程,我们将稍后介绍 Go 协程)。当我们的浏览器运行在单核 CPU 上时,CPU 将在浏览器的这两个组件之间进行上下文切换。它可能正在进行下载文件,一段时间后,切换到渲染区去渲染用户请求的HTML页面。这被称为并发。并发处理是从不同的时间点开始,分别交替运行。在本例中,下载和渲染在不同的时间点开始,并相互交替运行的。

假设同样的浏览器运行在多核 CPU 上。在这里文件下载模块和页面渲染模块可以同时运行在 CPU 的不同核上。这就是我们所说的并行。

 

并行不一定会加快运行速度,因为并行运行的组件之间可能需要相互通信。例如,在浏览器中,当文件下载完成时,应当对用户进行提醒,比如弹出一个窗口。于是,在负责下载的组件和负责渲染用户界面的组件之间,就产生了通信。在并发系统上,这种通信开销很小。如果这两个组件并行地运行在 CPU 的不同核上,这种通信的开销却很大。所以,并行不一定会加快运行速度!

Go对并发的支持

Go原生支持并发。在Go中,使用 Go 协程Goroutine)和信道channel)来处理并发。我们将在后面的教程中详细讨论它们。