Go 语言 并发与并行的区别
Go 是一种并发语言,而不是并行语言。在讨论 Go 中如何处理并发之前,我们必须首先了解什么是并发以及它与并行有何不同。
什么是并发?
并发是一种同时处理很多事情的能力。下面用一个例子来解释。
有一个人,在他早上慢跑时,假设他的鞋带松开了。现在这个人停止跑步,系好鞋带,然后又开始跑步。这是并发的经典示例。这个人能够处理跑步和系鞋带,也就是说这个人能够同时处理很多事情:)
什么是并行,它与并发有何不同?
并行是同时做很多事情。听起来可能类似于并发,但实际上是不同的。
我们还是用慢跑的例子来解释。在这种情况下,我们假设此人正在慢跑,并且跑步的同时还在他的 iPod 上听音乐。在这种情况下,这个人在慢跑的同时听音乐,也就是他在同时做很多事情。这称为并行。
其实细看的话会发现,并发强调的更是一种能力,而并行强调的是做的事情。
并发和并行 - 技术观点
我们通过现实世界的例子了解了什么是并发以及它与并行的不同之处。现在让我们从技术的角度来对二者进行一个对比,因为我们是极客:)
假设我们正在开发一个 Web 浏览器。Web 浏览器具有各种组件。其中两个是网页渲染区域和用于从 Internet 下载文件的下载器。假设我们已经构建了浏览器代码的结构,使得这些组件中的每一个都可以独立执行(这是使用 Java 等语言中的线程完成的,而在 Go 中,我们可以使用Goroutines来实现这一点,稍后会详细介绍)。当此浏览器在单核处理器中运行时,处理器将在浏览器的两个组件之间进行上下文切换。它可能会下载一个文件一段时间,然后它可能会切换到呈现用户请求的网页的 html。这称为并发。并发进程在不同的时间点开始,并且它们的执行周期重叠。在这种情况下,下载和渲染在不同的时间点开始并且它们的执行重叠。
假设同一个浏览器在多核处理器上运行。在这种情况下,文件下载组件和 HTML 渲染组件可能会在不同的内核中同时运行。这称为并行。
并行性并不总是执行效率更高更快。这是因为并行运行的组件可能必须相互通信。例如,在我们的浏览器的情况下,当文件下载完成时,这应该传达给用户,比如使用弹出窗口提示用户已经下载完成。这种通信发生在负责下载的组件和负责呈现用户界面的组件之间。这种通信开销在并发系统中很低。在组件在多个内核中并行运行的情况下,这种通信开销很高。因此,并行程序并不总是会导致更快的执行时间!
Go 中的并发支持
并发是 Go 编程语言的固有部分。在 Go 中使用Goroutines和通道处理并发。我们将在接下来的教程中详细讨论它们。