go - 映射并发使用
问题描述
我遇到了这段代码,想知道这是否需要一个 R/W Mutex。
method(){
var (
wg sync.WaitGroup
rwm sync.RWMutex
vcnRegionMap map[string][]core.Vcn
)
vcnRegionMap = make(map[string][]core.Vcn)
// This loops helps us in filtering unused regions
// for composition of region/vcnid ds
for _, regionName := range regions {
wg.Add(1)
go func(ctx context.Context, region string, vcnRegionMap map[string][]core.Vcn, wg *sync.WaitGroup, rwm *sync.RWMutex) {
// for locking maps
defer wg.Done()
// TODO: make this conditional if a region is specified
c.network.SetRegion(region)
vcnResponse, err := c.network.ListVcns(ctx, core.ListVcnsRequest{
CompartmentId: &c.cID,
})
if err != nil {
logger.Debug(err.Error())
}
if len(vcnResponse.Items) == 0 {
logger.Info("status 404: No Vcns found under the given OCID and region: %s", region)
return
}
logger.Info("status 200: Vcns found under the given OCID and region: %s", region)
for _, item := range vcnResponse.Items {
logger.Debug("Vcn object: %s", *item.DisplayName)
// maps are not concurrency safe
rwm.Lock()
defer rwm.Unlock()
vcnRegionMap[region] = append(vcnRegionMap[region], item)
}
}(ctx, regionName, vcnRegionMap, &wg, &rwm)
}
wg.Wait()
}
由于每个 goroutine 都有自己的 map 副本,Mutex 是否有帮助,我们可以避免它以减少延迟吗?
解决方案
您需要保护地图不被同时访问。代码是错误的,因为您正在读取锁定互斥锁,但写入地图。
for _, item := range vcnResponse.Items {
logger.Debug("Vcn object: %s", *item.DisplayName)
// maps are not concurrency safe
rwm.Lock()
vcnRegionMap[region] = append(vcnRegionMap[region], item)
rwm.Unlock()
}
请注意,此版本不使用defer
. 延迟操作在函数返回时运行,而不是在块结束时运行。您读取锁定互斥锁n
时间,每次迭代一次,然后在函数返回时释放所有互斥锁。
推荐阅读
- c++ - 内部可散列类声明失败
- mysql - 我需要使用 LENGTH 函数从 2 个不同的表中提取值,但只使用 1 个查询
- c# - 如何编写解析和检查列表值的 linq 语句
- python - 将列表字符串转换为变量列表
- javascript - 如何在 chrome 上从内部网站启动内部应用程序?
- c - Memcpy 覆盖 3 维数组中的区域
- java - 我正在尝试构建一个应用程序,它会在 wifi 状态更改时创建通知
- java - 为默认 recyclerView 创建展开动画(将视图的可见性从消失更改为可见)
- ruby-on-rails - Facebook 登录有时不会返回电子邮件,即使已获得授权
- javascript - 从视频标签中的所有帧拍摄快照