go - map var 快照的并发读/写
问题描述
我遇到了一个我无法理解的情况。在我的代码中,我使用的函数需要读取地图(但不写入,仅循环遍历此地图中现有数据的快照)。有我的代码:
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”在一个 go 例程中运行,只有一次,这个函数没有多次运行。许多其他函数正在使用相同的方法访问相同的“MapVar”,并随机产生“映射并发写入/读取”。我希望有人能向我解释为什么我的代码是错误的。
感谢您的时间。
编辑:为了澄清,我只是问为什么我的范围 MapSnapshot 会产生并发的地图写入/读取。我无法理解如何同时使用此映射,因为我使用同步互斥锁将真正的全局变量 (MapVar) 保存在本地变量 (MapSnapshot) 中。
编辑:解决。要在不使用相同引用的情况下将映射的内容复制到新变量中(从而避免映射并发读/写),我必须遍历它并使用 for 循环将每个索引和内容写入新映射。
感谢 xpare 和 nilsocket。
解决方案
这个函数没有多次运行。许多其他函数正在使用相同的方法访问相同的“MapVar”,它随机产生一个“map concurrent write/read”
当您传递 to 的值时MapVar.MyMap
,MapSnapshot
永远Map concurrent write/read
不会发生,因为该操作是用互斥锁包装的。
但是在循环中,错误可能会发生,因为实际上读取过程是在循环期间发生的。所以最好用互斥锁来包装循环。
MapVar.Lock() // lock begin
MapSnapshot := MapVar.MyMap
for _, a := range MapSnapshot {
// Map concurrent write/read occur here
// Some stuff
}
MapVar.Unlock() // lock end
更新 1
以下是我对您的论点的回应:
这个for循环很费时间,这个循环里面的东西很多,所以加锁会拖慢其他例程
根据您的说法The function "MyFunc" is run in a go routine, only once, there is no multiple runs of this func
,那么我认为将其MyFunc
作为 goroutine 执行并不是一个好的选择。
并且为了提高性能,最好让循环内的进程在 goroutine 中执行。
func MyFunc() {
for _, a := range MapVar.MyMap {
go func(a MyDatas) {
// do stuff here
}(a)
}
}
main() {
MyFunc() // remove the go keyword
}
更新 2
如果您真的想将复制到MapVar.MyMap
另一个对象中,将其传递给另一个变量将无法解决该问题(与或其他原始map
类型相比是不同的int
类型)。float32
请参考这个线程如何复制地图?
推荐阅读
- python - 如何从python输出中提取特定行
- node.js - 如何使用 axios 检查标头值
- scala - Spark java.lang.ClassCastException:scala.collection.mutable.WrappedArray 不能转换为 scala.collection.immutable.Seq
- c - char* 类型的变量,可以在迭代期间更改值
- java - 使用 Spring 从测试/资源加载资源/文件
- spring - 围绕@StreamListener 方法的Spring AOP - Spring Cloud Stream
- android - 如何知道 UnifiedNativeAd 是 NativeAppInstallAd 还是 NativeContentAd?
- javascript - 在 while 循环后停止执行代码(不中断)
- java - 已解决 [org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 2 个错误
- python - Plotly:如何在单个图中输出多个折线图?