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

时间:2014-05-29 05:54:07

标签: 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 
    }
}

你看到这个伪代码有什么问题吗? (就简陋而言)

2 个答案:

答案 0 :(得分:6)

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

您可以使用go test -race自动查找这些问题。

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

您可能希望阅读Go Memory Model文档,该文档清楚地解释了在goroutines中可见变量的变化。

答案 1 :(得分:3)

如果对数据竞赛不确定,请运行go run -race file.go,说的是,是的,会有比赛。

最简单的解决方法是使用sync.RWMutex

var a map[T]N
var lk sync.RWMutex
// uses the map
func goroutineA() {
    for (...) {
        lk.RLock()
        //actions on a
        lk.RUnlock()
    }
}

//refreshes the map
func gorountineB() {
    for (...) {
        otherTempA = make(map[T]N)
        //...initializes other tempA....
        lk.Lock()
        a = otherTempA
        lk.Unlock()
    }
}