gpt4 book ai didi

data-structures - 带范围的 Golang 并发 map 访问

转载 作者:IT老高 更新时间:2023-10-28 13:07:22 25 4
gpt4 key购买 nike

我有一张 map ,其中包含需要在清除 map 之前释放的对象。我很想在遍历 map 时迭代 map 并删除/释放对象。

这是一个模拟示例 https://play.golang.org/p/kAtPoUgMsq

由于迭代 map 的唯一方法是通过范围,我将如何同步多个生产者和多个消费者?

我不想读取锁定 map ,因为这会使迭代期间无法删除/修改键。

最佳答案

有很多方法可以让您从 map 中清理内容,而无需访问不雅的 map 。对您的应用程序有效的方法很大程度上取决于它在做什么。

0) 工作时只需锁定 map 即可。如果 map 不是太大,或者您有一些延迟容忍度,它可以快速完成工作(就花费在上面的时间而言),您可以继续考虑其他事情。如果以后变成问题,你可以再回到问题上来。

1) 将对象或指针复制出来并在持有锁的同时清除 map ,然后在后台释放对象。如果问题是释放本身的缓慢会使锁保持很长时间,那么这是解决此问题的简单解决方法。

2) 如果高效读取基本上是最重要的,请使用 atomic.Value。这使您可以用新的不同 map 完全替换一张 map 。如果写入基本上是您工作负载的 0%,那么高效的读取会平衡每次更改时创建新映射的成本。这种情况很少见,但确实会发生,例如,encoding/gob 具有以这种方式管理的类型的全局映射。

3) 如果这些都不能满足您的所有需求,请调整存储数据的方式(例如,对 map 进行分片)。自己用 16 个映射和哈希键替换您的映射,以决定一个事物属于哪个映射,然后您可以一次锁定一个分片,以进行清理或任何其他写入。

还有释放和使用之间的竞争问题:goroutine A 从 map 中获取一些东西,B 清除 map 并释放东西,A 使用释放的东西。

一种策略是在您使用或释放​​每个值时锁定它;那么你需要锁而不是全局锁。

另一个是容忍种族的后果,如果它们是已知的并且不是灾难性的;例如,net.Conns 的文档明确允许并发访问,因此关闭正在使用的连接可能会导致对其的请求出错,但不会导致未定义的应用行为。但是,您必须真正确定自己知道自己要进入的内容,因为many benign-seeming races aren't .

最后,也许您的应用程序已经确保不会释放正在使用的对象,例如对对象有一个安全维护的引用计数,并且只释放未使用的对象。那么,当然,您不必担心。

尝试以某种方式用 channel 替换这些锁可能很诱人,但我看不到任何 yield 。 很好当您可以设计您的应用程序时主要考虑进程之间的通信而不是共享数据,但是当您确实有共享数据时,假装没有用处。排除对共享数据的不安全访问是锁的用途。

关于data-structures - 带范围的 Golang 并发 map 访问,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34080734/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com