我有一个地图,由goroutine A使用,并在goroutine B中一次更换一次.通过替换我的意思是:
var a map[T]N
// uses the map
func goroutineA() {
for (...) {
tempA = a
..uses tempA in some way...
}
}
//refreshes the map
func gorountineB() {
for (...) {
time.Sleep(10 * time.Seconds)
otherTempA = make(map[T]N)
...initializes other tempA....
a = otherTempA
}
}
Run Code Online (Sandbox Code Playgroud)
你看到这个伪代码有什么问题吗?(在统一性方面)
代码不安全,因为对指针值的赋值和读取不保证是原子的.这可能意味着当一个goroutine写入新指针值时,另一个可能会看到来自旧值和新值的混合字节,这将导致程序以令人讨厌的方式死亡.可能发生的另一件事是,由于代码中没有同步,编译器可能会注意到goroutineA中没有任何内容可以更改,并将tempA := a语句提升出循环.这意味着您将永远不会看到新的地图分配,因为其他goroutine会更新它们.
您可以使用go test -race自动查找这些类型的问题.
一种解决方案是使用互斥锁锁定对地图的所有访问.
您可能希望阅读Go Memory Model文档,该文档清楚地解释了在goroutines中何时可以看到变量的变化.