在我的代码中存储配置的一种常见模式是受RWMutex保护的“map [string] interface {}”,但是通常在应用启动后(可以在多个go-routine中触发),该映射完全变为只读状态。因此,我觉得从某个时候开始,读过的RWMutex应该是不必要的。

此配置映射的示例位于
http://play.golang.org/p/tkbj9DBok_

让我想到这一点的一个事实是,在一些生产代码中,它实际上是以这种不 protected 方式访问共享对象的方法(尽管在初始化后大多数情况下是只读的),我了解使用RWMutex进行保护的正常方法,但是很有趣部分原因是该格式错误的代码在过去几个月中没有遇到问题。

是真的,在某个准确的“时间点”上将写入内容从高速缓存刷新到内存中并且保证不再需要写入操作之后,读取实际上可以不使用RWMutex.RLock吗?如果是,在什么时间点或如何设置无锁访问之前的条件?

最佳答案

只要没有人在修改映射,多个线程就可以安全地一次读取它。不幸的是,没有任何锁定,您将无法确保要更新 map 时没有其他人正在阅读 map 。

因此,一种解决方案是从不更新 map ,而以原子方式替换它。此处可以使用read-copy-update算法。而不是直接访问 map ,因此您需要取消引用指针以访问 map 。要更新它,您可以执行以下操作:

  • 获取“更新锁”互斥体。
  • 复制 map 。您想手动复制所有键/值:简单分配将不起作用,因为 map 是引用类型。
  • 对 map 副本进行更改。
  • 使用StorePointer包中的sync/atomic原子更新指向实时 map 的指针以指向您的新 map 。
  • 释放互斥量。

  • 在(4)中的原子更新之前运行的所有内容都将看到旧映射,而在之后的所有内容将看到新映射。这些goroutine绝不会从正在写入的映射中读取,因此不需要RWMutex

    关于concurrency - 什么时候可以安全地访问互斥锁保护的变量而无需锁定?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/31198562/

    10-11 23:19
    查看更多