Go这样检测Data Race让并发程序又简单了许多
大家好,我是极客老墨。 写并发代码最怕什么?不是死锁,不是性能问题,而是那些偶尔才出现、难以复现的诡异 bug。这些 bug 的罪魁祸首往往就是 Data Race(数据竞争)。 什么是 Data Race? Data Race 的定义很简单:当两个或多个 goroutine 同时访问同一个变量,且至少有一个在写入时,就会发生数据竞争。 这就像两个人同时在一张纸上写字,最后的结果可能是谁的字都不完整,或者干脆就是一团乱码。 举个例子: 1var counter int 2 3func increment() { 4 counter++ // 看起来是一行代码,实际上是三个操作:读取、加1、写入 5} 6 7func main() { 8 go increment() 9 go increment() 10 time.Sleep(time.Second) 11 fmt.Println(counter) // 结果可能是 1,也可能是 2 12} 这段代码看起来没问题,但 counter++ 并不是原子操作。两个 goroutine 可能同时读到 0,然后都写入 1,最终结果就是 1 而不是期望的 2。 顺便说一句,Data Race 和 Race Condition 是两个不同的概念,很多人会混淆。我之前翻译过一篇文章专门讨论这个问题,感兴趣可以看看。 Go 内存模型定义了 Happens-Before 规则来保证程序执行的顺序性,这和 Java 内存模型的思路类似。但光有规则还不够,Go 从 1.1 版本开始提供了 Race Detector,让我们能在运行时检测出这些问题。 ...