【发布时间】:2018-10-15 08:26:08
【问题描述】:
我遇到了我无法理解的情况。在我的代码中,我使用的函数需要读取地图(但不写入,仅循环遍历此地图中现有数据的快照)。有我的代码:
type MyStruct struct {
*sync.RWMutex
MyMap map[int]MyDatas
}
var MapVar = MyStruct{ &sync.RWMutex{}, make(map[int]MyDatas) }
func MyFunc() {
MapVar.Lock()
MapSnapshot := MapVar.MyMap
MapVar.Unlock()
for _, a := range MapSnapshot { // Map concurrent write/read occur here
//Some stuff
}
}
main() {
go MyFunc()
}
函数“MyFunc”在一个goroutine中运行,只有一次,这个func没有多次运行。许多其他函数正在使用相同的方法访问相同的“MapVar”,并随机产生“映射并发写入/读取”。我希望有人能向我解释为什么我的代码是错误的。
感谢您的宝贵时间。
编辑:澄清一下,我只是在问为什么我的范围 MapSnapshot 会产生并发映射写入/读取。我无法理解如何同时使用此映射,因为我使用同步互斥体将真正的全局变量 (MapVar) 保存在本地变量 (MapSnapshot) 中。
编辑:已解决。要在不使用相同引用的情况下将映射的内容复制到新变量中(从而避免映射并发读/写),我必须遍历它并使用 for 循环将每个索引和内容写入新映射。
感谢 xpare 和 nilsocket。
【问题讨论】:
-
我不明白你想要达到的目标,你能否解释得更清楚些。
-
这是 100% 错误的。
MapSnapshot := MapVar.MyMap确实不生成可以与“原始”同时使用的副本。 -
你说 MapVar.MyMap 的指针和 MapSnapshot 是一样的?它是一个新的 var 声明,所以它应该只是一个副本。你能解释一下为什么我在这一点上错了吗?
-
@Anarz 映射是一个复杂的数据结构,它不是整数或字符串值,可以通过单个赋值进行复制。它还包含对其他事物的其他几个引用,顺便说一句,
map[x]x本身就是一个引用。阅读this 了解更多信息。
标签: go