Go 是一种并发语言,而不是并行语言**。在讨论如何在 Go 中处理并发之前,我们必须首先了解什么是并发以及它与并行性的不同之处。
什么是并发?
并发是一次处理大量事情的能力。让我们用一个例子来解释。
假如一个人慢跑。在他早晨慢跑时,我们可以说他的鞋带已经解开了。现在,这个人停止跑步,绑鞋带,然后又开始跑步。这是并发的典型示例。这个人能够处理跑鞋和系鞋带,也就是说,这个人能够同时处理很多事情:)
什么是并行性,它与并发性有什么不同?
并行同时做了很多事情。它可能听起来类似于并发,但它实际上是不同的。
让我们用同样的慢跑例子来更好地理解它。在这种情况下,我们假设这个人正在慢跑并且还在他的 iPod 中听音乐。在这种情况下,这个人同时在慢跑和听音乐,也就是说,他正在做很多事情。这称为并行性。
并发与并行 - 技术观点
我们理解什么是并发性以及它与使用真实世界示例的并行性有何不同。现在让我们从更技术的角度来看待它们,因为我们是极客:)。
假设我们正在编写一个 web 浏览器。web 浏览器有各种组件。其中两个是 web 页面呈现区域和用于从网上下载文件的下载加载程序。让我们假设我们已经以这样一种方式构造了浏览器的代码,即每个组件都可以独立执行(这是使用 Java 等语言中的线程完成的,在 Go 中我们可以使用 Goroutines 来实现这一点,后面会详细介绍)。当此浏览器在单内核处理器中运行时,处理器将在浏览器的两个组件之间切换上下文。它可能正在下载文件一段时间,然后可能切换到呈现用户请求的 web 页面的 html。这就是所谓的并发。并发进程在不同的时间点开始,它们的工作周期重叠。在这种情况下,下载和渲染在不同的时间点开始,并且它们的执行重叠。
假设同一个浏览器运行在多核处理器上。在这种情况下,文件下载组件和HTML呈现组件可能在不同的内核中同时运行。这就是所谓的并行。
并行并不代表拥有更快的执行时间。这是因为并行运行的组件可能会彼此通信。例如,在我们的浏览器中,当文件下载完成时,应该将此信息传递给用户,比如使用弹出窗口。这种通信发生在负责下载的组件和负责呈现用户界面的组件之间。在并发系统中,这种通信开销很低。在组件在多个内核中并行运行的情况下,这种通信开销很高。因此,并行程序并不代表拥有更快的执行时间!
在Go中支持并发
并发是 Go 编程语言的与生俱来的部分。并发性在 Go 中使用 goroutine 和 channels 来处理。我们将在接下来的教程中详细讨论它们。