Go 映射并发使用

Go 映射并发使用,go,go-map,Go,Go Map,我遇到了这段代码,想知道这是否需要一个R/W互斥 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 com

我遇到了这段代码,想知道这是否需要一个R/W互斥

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()
}

当每个go例程都有自己的map副本时,互斥锁是否有帮助?我们是否可以避免它以减少延迟?

您需要保护map不被并发访问。代码是错误的,因为您正在读取并锁定互斥锁,但正在写入映射

 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()
        }

请注意,此版本不使用
延迟
。延迟操作在函数返回时运行,而不是在块结束时运行。每次迭代读取一次锁定互斥锁
n
,然后在函数返回时释放所有互斥锁。

我没有看到复制
vcnRegionMap
映射的任何地方。必须始终同步对任何值的并发修改。映射头的副本传递给函数,而不是映射的深度副本。每个goroutine仍在修改相同的基础映射。Go中的映射与切片一样,都是有效的引用类型。@f-z-N:如果是为了您自己的理解,那么投票就无关紧要了。它很可能最终被否决,因为如此频繁地重复关于这个主题的答案对整个网站没有多大用处。@f-z-N,你可以用任何一种方法。我个人会删除这些参数以消除混淆,因为四个参数中有三个是有效关闭的。您必须确保仍然复制
regionName
,这是我用
regionName:=regionName
惯用语所做的。@JimB,这真的可以吗?这仍然是对地图的书写。你不会破坏地图,但如果没有锁,它会很活泼。是的,你是对的,从技术上讲,这是一个写操作,即使密钥是相同的。问题根本不是关于分片,但这也有一场比赛可能值得一提。