为何存在data race?请求解析Dave Cheney文章中的示例
解析示例中的数据竞争(Data Race)
先看文中的核心代码片段:
var data int func main() { go func() { data = 1 }() // 写入操作 if data == 0 { // 读取操作 fmt.Println("data is 0") } time.Sleep(time.Second) }
这个代码存在数据竞争的原因很直接:
- 两个并发执行的 goroutine(主 goroutine 和新启动的匿名 goroutine)同时访问了同一个变量
data - 其中一个是写入操作,另一个是读取操作,且二者之间没有任何同步机制(比如互斥锁、channel、原子操作等)来约束执行顺序和内存可见性。
Go 的内存模型不会为这种无同步的并发读写提供任何保证:
- 主 goroutine 可能永远读不到新 goroutine 写入的
1——因为 CPU 缓存、编译器指令重排等优化,写入的结果可能不会及时同步到主 goroutine 能访问的内存空间 - 程序的输出完全不可预测,有时候会打印 "data is 0",有时候不会,完全取决于调度器的执行顺序和内存同步时机。
别被最后的 time.Sleep 误导,它不是同步原语,只能让程序等待一段时间,但无法保证新 goroutine 的写入操作对主 goroutine 可见。只有使用 Go 官方认可的同步机制,才能避免这类数据竞争。
内容的提问来源于stack exchange,提问作者John Smith
相关产品推荐
相关产品推荐

