- 这一部分有多重要。
- 这一部分性能提升了多少。
数据竞争是并发程序中最常见的,也是最难发现的并发问题,所幸的是,Go内置了在一定程度上可以发现竞争问题。你可以在测试数据竞争检测器(data race detector),或者运行程序时使用-race开启数据竞争检测器,或者在编译程序时开启,编译好的二进制程序在运行时也可以开启数据竞争检测:
go test -race mypkg // 测试mypkg包
go run -race mysr
因为并发编程中有竞争条件和数据竞争的问题,我们才需要将代码片段设定为临界区,通过使用Mutex等同步原语将临界区保护起来。接下来,我们来熟悉Go标准库的Mutex 的使用方法,看看它是如何保护临界区,解决竞争条件和数据竞争的问题的。
一个并发问题有时候,我们很清楚地知道临界区或者共享资源,能主动地发现数据竞争问题;但是有时候,数据竞争问题却不那么容易被发现,比如下面这段代码,你认为有数据竞争
一般来说,正如我们平常理解的那样,将串行程序修改为并行程序之后,其性能会得到提升。但也不是绝对的,在某些情况下,串行编程性能反而更好。
下面这个例子是快速排序的串行实现。
// 快速排序中的分区,把a分成左右两部分,左边部分小于右边部分
func partition(a []int, lo, hi int) int {
pivot := a[hi] // 将最后一个值作为分界值
i := l
阿姆达尔定律(Amdahl's Law,Amdahl's Argument),计算机科学界的一个经验法则,因IBM公司计算机架构师吉恩·阿姆达尔而得名。阿姆达尔曾致力于并行处理系统的研究,他进行了一项富有洞察力的观察:提升系统的一部分性能对整个系统的性能有多大影响。这一观察被称为阿姆达尔定律:
当提升系统的一部分性能时,对整个系统性能的影响取决于:
假
并发是同时处理很多事情,并行是同时做很多事情。
并发是同时处理很多事情,有时间段的概念,这些事情可能会有一个先后顺序,但是会在这个时间段内去做。从这个时间段来看,这些事情都被处理了。
比如我在编写代码的同时还在听着音乐,这两件事情如果被调度在同一个CPU上,它们是并发执行的。
并行是在同一个时间点有多件事情都在做。如果手头阔绰,我还可以买一台机器放在旁边,打开Markdown编辑器编写文章的内容,同时音乐播放器在播放抖音上最流行的歌曲。这两台服务器可以并行地执行,在同一个时刻,两台服务器都在做着事情,这是并行。
并发和并行并不相同,但是相关。如图,左边并发,右边并行。 ![并发vs并行
当今很多高级编程语言都支持并发编程,但是Go语言绝对是很特殊的那一个,一开始它就从语言设计上为并发编程提供了最简单的方式,并且设计了对线程更轻量级的goroutine,还为CSP模型提供了容易使用的channel类型,并将其作为内建类型直接提供。
2019年,在Go Time对Rob Pike和Robert Griesemer的访谈节目中,Rob Pike 谈到发明Go语言的想法时说道,“我们听到了一个C++新版本发