并发写入包含Golang中另一个Map的Map

时间:2017-10-01 15:43:19

标签: go concurrency

在Golang中,我们必须将并发更改同步到Map。如果我的地图包含另一个这样的地图:

map[string]map[string]*CustomStruct

..在编写内容时,我是否必须在所有这些内容中使用锁定

如果我将内容写入内部地图 - >外部地图也将被更改,因此我仍然需要同步外部地图的更改。

如果我锁定外部地图的更改 - >没有人可以写入内部地图 - >锁定内部地图是没有意义的。

我是对的,还是以不同的方式运作,我必须锁定所有地图?

2 个答案:

答案 0 :(得分:0)

我的理解是这里没有任何硬性规定。

例如,您可以通过甚至不存储在地图上的互斥锁协调所有地图写入,任何互斥锁与地图之间没有固有的链接 - 它只是关于如何使用它们来协调对数据的访问。 / p>

基本上,如果锁定单个元素,您将看到对锁的争用较少,因为锁的获取频率较低,如果对所有映射使用外部锁,则会有更多争用,因为更多进程将尝试获取相同的锁定将减少您的流程可以完成的实际工作量。

最终由您决定哪种方法最适合您的用例

帮助:

go 1.9中提供了一个新工具,允许您对锁争用进行基准测试,以了解哪种方法对您的应用程序最有效。

使用-race标记构建和运行您的应用将有助于确定锁是否正常工作

您还可以查看我尚未玩过的新同步地图,但我理解为您处理此问题:

usort

答案 1 :(得分:0)

简单(并且最可能足够好)的解决方案是使用保护整个结构的互斥锁。它可以是常规互斥锁或读写互斥锁,以防读取比写入更频繁。这很容易实现,易于推理,并且在绝大多数情况下它都可以完成这项工作。

另一方面,如果您正在寻找挑战,那么您可以将其转化为多个方向:

  • 每个顶级映射键都有一个顶级读写互斥锁和一个(简单或读写)互斥锁。在向顶级地图添加或删除条目时,写入锁定顶级互斥锁;否则读取锁定它,获取特定于条目的锁定并读取或写入条目(也是一个映射)。
  • 确定您想要什么样的并行性,并将顶级地图拆分为碎片,其中的键根据散列和每个碎片的一个互斥进行分片。然后,只要它们位于不同的分片中,您就可以对多个键进行并行写入(键添加和删除)。
  • 也将第二种方法应用于二级地图。疯了! :O)

但是,严肃地说,除非这张地图很大,否则你的大部分应用程序都只是添加和删除它的内容,并且你愿意花大量精力进行基准测试和调整你的实现,然后继续单锁方法。在一般情况下,它实际上要快得多,作为奖励,实施起来很简单。

相关问题