Golang,与当地地图的竞争条件

时间:2014-04-10 12:01:36

标签: go race-condition goroutine

我似乎完全不了解Go中的地图。

我有这段代码:

fetch := map[string]int{some data}

for condition {
    fetchlocal := map[string]int{}

    for key, value := range fetch {
        if condition {
            fetchlocal[key] = value
        }
    }

    go threadfunc (fetchlocal)
}

现在,无论threadfunc函数使用fetchlocal变量,Go(go -race)都会发出警告:数据竞争。我也有一些恐慌。但为什么? fetchlocal变量不被任何其他goroutine使用。

有人可以开导我吗?

1 个答案:

答案 0 :(得分:1)

我假设您的fetch := map[string]int{some data}实际上应该是:fetch := map[string][]int{..some data..}

要成为比赛,threadfunc必须更改fetchlocal内的值,否则必须更改fetch内的值。

这就是切片实际上是:

type SliceHeader struct {
        Data uintptr
        Len  int
        Cap  int
}

当您将元素从一个地图复制到另一个地图时,您执行切片的深层复制(您只是创建一个具有相同数据,Len,Cap的新结构),如此说fetch["foo"].Data == fetchlocal["foo"].Data

因此,您可以说fetch[someExistingKey] = someNewValue这不会与threadfunc竞争,但如果您说fetch[someExistingKey][x] == foobarfetchlocal[someExistingKey][x] == foobar,竞赛将会开始。

如果fetchlocal需要threadfunc进行变异,您可以将内循环更改为:

for key, value := range fetch {
    if condition {
        newVal := make([]int, len(value))
        copy(newVal, val)
        fetchlocal[key] = newVal
    }
}

或者,在变异之前根据需要在threadfunc内进行复制。

P.S。如果您在这两个循环运行时共享了实际threadfunc或正在修改fetch的代码,我们将能够提供更多帮助。