这是一个模拟的例子
https://play.golang.org/p/kAtPoUgMsq
由于迭代地图的唯一方法是通过范围,我如何同步多个生产者和多个消费者?
0)只要你在工作时锁定地图.如果地图不是太大,或者你有一些延迟宽容,它可以快速完成工作(在你花费的时间上),你可以继续思考其他的东西.如果以后出现问题,那么可以回到问题.
1)复制对象或指针并按住锁定清除地图,然后在后台释放对象.如果问题是释放缓慢会使锁持续很长时间,那就是简单的解决办法.
2)如果高效的读取基本上都是重要的,请使用atomic.Value.这可以让您完全用一个新的和不同的地图替换一个地图.如果写入本质上是您的工作负载的0%,高效读取可以平衡每个更改创建新映射的成本.这很罕见,但它发生,例如,encoding / gob具有以这种方式管理的类型的全局映射.
3)如果没有人做任何你需要的一切,调整你如何存储数据(例如划分地图).用16个地图和散列键自动替换地图,以决定一个属于哪个地图,然后一次可以锁定一个碎片,以进行清理或其他任何写入操作.
还有一个发布和使用之间的竞争的问题:goroutine A从地图获取东西,B清除地图并释放该东西,A使用发布的东西.
一个策略是在使用或释放它时锁定每个值;那么你需要锁,而不是全局锁.
另一个原因是容忍种族的后果,如果它们是已知的,而不是灾难性的;例如,net.Conns的并发访问权限由其文档明确允许,因此关闭使用中的连接可能会导致请求发生错误,但不会导致未定义的应用程序行为.你必须真的确定你知道你在做什么,但是,因为many benign-seeming races aren’t.
最后,也许您的应用程序已经确保没有使用对象被释放,例如对象上有一个安全维护的引用计数,只释放未使用的对象.那么当然,你不必担心.
尝试用渠道替代这些锁可能是诱人的,但我看不到任何收获.很好,当您可以设计您的应用程序思想时,主要是在进程之间的通信而不是共享数据,但是当您有共享数据时,没有用于假装.排除对共享数据的不安全访问是什么锁.