前言
两个或多个 goroutine 访问同一个资源(如变量或数据结构),并尝试对该资源进行读写而不考虑其他 goroutine。这种类型的代码可以创建你见过的最疯狂和最随机的 bug。通常需要大量的日志记录和运气才能找到这些类型的bug。
提示:以下是本篇文章正文内容,下面案例可供参考
一、data race 会出现什么结果呢?
例子 一
package main
import (
"fmt"
"sync"
)
var Counter int = 0
var wg sync.WaitGroup
func main() {
for i := 0; i < 100000; i++ {
for routine := 1; routine <= 2; routine++ {
wg.Add(1)
go Routine(routine)
}
wg.Wait()
}
fmt.Println(Counter)
}
//399718 399574 399634
func Routine(id int) {
for conut := 0; conut < 2; conut++ {
Counter++
}
//399618 399650
wg.Done()
}
399718 399574 399634 这是上面代码 执行3次的结果 每次都不一样
我们来分析一下:
最好的情况 4 Routine1 读 和 写 执行完 Routine2 才开始执行 读取到的是结果加2的数据 在次累加
最坏的情况:2 Routine1 读 和 写 中间 Routine2 开始执行了 读取到未累加的数据
这里还有一个问题 i++ 是不是原子的?
在上面这个例子执行完就知道不是原子的了。我们来看看 低层汇编的代码
0x0031 00049 (main.go:29) MOVQ "".Counter(SB), AX