设置和访问并发goroutines中的指针

Ale*_*rev 3 go

我有一个地图,由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)

你看到这个伪代码有什么问题吗?(在统一性方面)

Pau*_*kin 7

代码不安全,因为对指针值的赋值和读取不保证是原子的.这可能意味着当一个goroutine写入新指针值时,另一个可能会看到来自旧值和新值的混合字节,这将导致程序以令人讨厌的方式死亡.可能发生的另一件事是,由于代码中没有同步,编译器可能会注意到goroutineA中没有任何内容可以更改,并将tempA := a语句提升出循环.这意味着您将永远不会看到新的地图分配,因为其他goroutine会更新它们.

您可以使用go test -race自动查找这些类型的问题.

一种解决方案是使用互斥锁锁定对地图的所有访问.

您可能希望阅读Go Memory Model文档,该文档清楚地解释了在goroutines中何时可以看到变量的变化.