【发布时间】:2020-06-23 04:42:53
【问题描述】:
我有一个包含sync.Map 的类型,其中映射中的键是字符串,值是切片。我在地图中插入项目的代码如下:
newList := []*Item{item}
if result, ok := map.LoadOrStore(key, newList); ok {
resultList := result.([]*Item)
resultList = append(resultList, item)
map.Store(key, resultList)
}
这不是并发安全的,因为切片可以通过多个调用同时加载和修改。这段代码非常脆弱,所以我尝试将其修改为:
newList := []*Item{item}
if result, ok := map.LoadOrStore(key, &newList); ok {
resultList := result.(*[]*Item)
*resultList = append(*resultList, item)
}
所有这一切都是使问题确定性地发生。所以,我正在尝试找到一种方法来创建一个可以同时添加的切片图。我的直觉是在添加列表时使用sync.Mutex 锁定列表,但为了保持对sync.Map 的并发访问,我还需要创建sync.Mutex 对象的映射,如下所示:
newLock := sync.Mutex{}
raw, _ := lockMap.LoadOrStore(key, &newLock)
lock := raw.(*sync.Mutex)
newList := []*Item{item}
if result, ok := map.LoadOrStore(key, &newList); ok {
lock.Lock()
resultList := result.(*[]*Item)
*resultList = append(*resultList, item)
lock.Unlock()
}
有没有更简单的方法来解决这个问题?
【问题讨论】:
-
struct { *sync.Mutex, []*Item }的地图怎么样? -
@phonaputer 这是一个有趣的解决方案。没想到
-
嗯,这和你现在的想法没什么不同。但是很高兴能够使用嵌入的
*sync.Mutex做类似SafeItems.Lock()的事情。不用处理两张地图真是太好了。 -
同意。我实现了它,它解决了我的问题。您想获得此问题的答案吗?
-
当然我会带你去。
标签: go concurrency