Go语言 并发

导言


并发

Go 是一门并发语言,而不是并行语言。在谈论 Go 如何实现并发前,我们必须理解:

  1. 什么是并发?
  2. 并发与并行的区别。

并发是什么?

并发是一种能力,它使我们能一次处理多件事情。这个说起来有些抽象,下面用例子解释吧~

以一个跑步的人为例。在他晨跑时,假设他的鞋带松了。此时,他会停下来,在系紧鞋带后,重新开始跑步。这是一个经典的并发实例。这人能跑步,也能系鞋带,也就是说,他一次可以做多件事情。


什么是并行?它和并发有何不同

并行也是一种能力,这种能力使我们能在同一时刻,处理多件事情。听起来,它和并发是类似的,但实际上,这是两个不同的概念。

我们继续以上面跑步的人为例。假设此时,他一边跑步,一边听音乐。在这种情况下,跑步和听音乐是同时进行的,也就是说,在同一时刻,他能做多件事情 — 这就叫并行。

并发与并行 — 技术角度

使用现实世界的例子,我们理解了并发,也理解了它与并行的不同。但是,因为我们是极客,我们得从技术角度来看待它们。

假设我们正在编写一个浏览器。这个浏览器有很多组件 — 组件包括了网页渲染区域,以及一个下载器。假设我们已经编写好了程序代码,并保证组件之间能独立运行 (在 Java 中,我们能使用线程实现这样的功能,而在 Go 中,我们能使用协程)。

当这个浏览器运行在单核 CPU 时,CPU 的上下文,会在这两个线程之间来回切换。CPU 可能先花费一段时间下载文件,之后转向渲染 html 页面的工作。这就是所谓的并发。
并发的线程会在不同的时间点启动,并且,它们的执行是交叠的。对于上面的例子,下载线程和渲染线程会在不同的时间点开启,并且交叠执行。

假设此时,这个浏览器在多核 CPU 上运行。此时,下载线程和渲染线程可能同时在不同的 CPU核 上运行 — 即可能出现:下载线程在 a 核 运行,而渲染线程在 b核 运行。这就是所谓的并行。

Go语言 并发
并行并不能保证缩短执行时间,这是因为并行线程可能需要进行交互。

举个例子,在浏览器例子中,当下载完成时,浏览器需要使用弹窗告诉用户:下载已经完成了。此时,下载线程就需要与渲染线程进行交互了 — 因为弹窗是渲染线程做的事情。在并发系统中,这样的交互开销很低。而当线程们并行地运行在不同的 CPU核 上时,这样的交互开销很高。因此,并行程序并不总能缩短执行时间。

Go语言 对并发的支持

并发是 Go语言 固有的一部分。Go语言 使用协程和通道实现并发。

以上就是对并发的简单介绍,祝你暴富~


原作者留言

优质内容来之不易,您可以通过该 链接 为我捐赠。


最后

感谢原作者的优质内容。

这是我的第七次翻译,欢迎指出文中的任何错误。