sh *_* sh 5 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)
}
Run Code Online (Sandbox Code Playgroud)
现在,无论threadfunc函数使用fetchlocal变量,Go(go -race)都会发出警告:数据竞争.我也有一些恐慌.但为什么?fetchlocal变量不被任何其他goroutine使用.
有人可以开导我吗?
我假设你fetch := map[string]int{some data}实际上应该是:fetch := map[string][]int{..some data..}。
要成为一场竞赛,threadfunc必须改变 内的值fetchlocal,或者必须有其他东西改变 内的值fetch。
这就是说切片实际上是:
type SliceHeader struct {
Data uintptr
Len int
Cap int
}
Run Code Online (Sandbox Code Playgroud)
当您将元素从一个映射复制到另一个映射时,您并没有对切片进行深层复制(您只是使用相同的 Data、Len、Cap 创建一个新结构),也就是说fetch["foo"].Data == fetchlocal["foo"].Data。
因此你可以说fetch[someExistingKey] = someNewValueand 这不会与 比赛threadfunc,但如果你说fetch[someExistingKey][x] == foobarorfetchlocal[someExistingKey][x] == foobar比赛将会进行。
如果fetchlocal需要改变,threadfunc您可以将内部循环更改为:
for key, value := range fetch {
if condition {
newVal := make([]int, len(value))
copy(newVal, val)
fetchlocal[key] = newVal
}
}
Run Code Online (Sandbox Code Playgroud)
threadfunc或者,在变异之前根据需要在内部进行复制。
threadfuncPS如果您分享了在这两个循环运行时正在修改的实际代码或代码fetch,我们将能够提供更多帮助。