并发和并行在服务端开发中是常见的概念,golang 的模式也经常被人讨论。那么在 golang 中是如何体现这两者呢?
定义
首先,明确下定义(不同人理解不同,此处仅取一种常见的看法)。
- 并发,将程序设计为若干独立运行的模块,同时处理多件事,和结构相关的
- 并行,利用多核cpu并行完成运算(可能是相关的),同时做多件事,和执行相关的
go 是并发的语言,而非并行语言。
区分
从定义出发,再详细讨论下个人的理解。
并发:我们的应用中同时有多个(很多时候是不相关的)任务在运行,如果只有一个 cpu,则只能说在一段时间内是并发的。如果有多个 pu,可以认为是在同一时刻是并发的。说的是同时处理多个任务。
并行:我们的应用把一个大的任务拆成几个子任务,然后这几个子任务是并行处理的。在多个 cpu上,在同一时刻处理了多个子任务。说的是处理某个具体的任务。
可以并发而不并行(不拆分子任务),也可以并行而不并发(只用子任务),可以既不并行也不并发(线性完成任务),也可以既并行又并发(同时处理多个任务,同时拆分子任务。此种情况需要注意,有可能性能提升不明显却带来额外开销)。
结论
无论大家理解有何不同,最终还是要落实到实践。对于 golang 来说,goroutine 天然代表了并发,是大家应该优先使用的 golang 编程范式。如果某项任务可以细分,指定若干 goroutine 去执行,也接近并行的概念。个中区别,大家细细体会吧。