Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Loops 在对映射进行迭代同时修改映射时,如何使用RWMutex_Loops_Go_Concurrency_Mutex_Go Map - Fatal编程技术网

Loops 在对映射进行迭代同时修改映射时,如何使用RWMutex

Loops 在对映射进行迭代同时修改映射时,如何使用RWMutex,loops,go,concurrency,mutex,go-map,Loops,Go,Concurrency,Mutex,Go Map,我想使用映射的键从API请求一些东西,然后根据API的响应更新相应的值 我猜是下面的代码 或者在迭代之前收集数组中的映射键 然后使用数组项发出请求并修改映射 wg:=&sync.WaitGroup{} 工作组添加(len(someMap)) sem:=信号量.NewWeighted(maxWorkers) ctx:=context.TODO() 互斥体:=&sync.RWMutex{} mutex.RLock() 对于k,v:=范围someMap{ mutex.RUnlock() 围棋(k,v)

我想使用映射的键从API请求一些东西,然后根据API的响应更新相应的值

我猜是下面的代码

或者在迭代之前收集数组中的映射键 然后使用数组项发出请求并修改映射

wg:=&sync.WaitGroup{}
工作组添加(len(someMap))
sem:=信号量.NewWeighted(maxWorkers)
ctx:=context.TODO()
互斥体:=&sync.RWMutex{}
mutex.RLock()
对于k,v:=范围someMap{
mutex.RUnlock()
围棋(k,v){
推迟工作组完成()
sem.Acquire(ctx,1)
res,err:=API.REQUEST(k)
结构方程组发布(1)
如果错误!=零{
返回
}
v、 SomeElement=res.SomeElement
互斥锁
someMap[k]=v
mutex.Unlock()
}(k,v)
mutex.RLock()
}
mutex.RUnlock()
wg.Wait()

你所做的应该是可行的。但是,请注意,在runlock和rlock之间,您所做的只是创建一个goroutine,因此您将有许多goroutine等待锁定。首先迭代映射,然后进行修改,这样更易于阅读和调试。或者,您可以更改映射并使用
map[keytype]struct{value*valuetype}
,这样您就不需要锁定映射,运行goroutine而不需要互斥体。每个goroutine都将修改map[k].value而不是map[k]。

虽然IIRC可以成功地锁定range子句,但这里的问题是,您可能最终会或可能不会迭代新的键。根据规范:
如果在迭代过程中创建了映射条目,则该条目可能在迭代过程中生成,也可能被跳过。我只想收集你想要迭代的密钥,让代码更容易理解。谢谢你的回答!使用额外的数组可以将代码简化一点(这在IMO中更可取)。但我有点不喜欢分配不必要的内存。尽管它甚至可以加快代码的速度,因为它可以消除所有的RLock操作,而且映射也不是真正的“大”。不会创建任何条目,因为我只想更新现有条目。如果映射没有那么大,那么分配一部分密钥也没什么大不了的。通过网络执行单个API调用可能会分配更多数量级的资源。注意在没有实际数据的情况下进行优化。相关/可能重复的