concurrency - 什么时候可以在不锁定的情况下安全地访问受互斥锁保护的变量?

标签 concurrency go synchronization race-condition

在我的代码中存储配置的一个常见模式是由 RWMutex 保护的“map[string]interface{}”,但通常在应用程序启动后(可以在多个 go-routine 中触发), map 变为完全只读。所以我有一种感觉,从某个时间点开始,读取时的 RWMutex 应该是不必要的。

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

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

在某个准确的“时间点”将写入从缓存刷新到内存并保证不再需要写入后,读取实际上可以在没有 RWMutex.RLock 的情况下进行,这是真的吗?如果是,无锁访问的时间点是什么时候或者如何设置条件?

最佳答案

只要没有人在修改 map ,多个线程同时读取它应该是安全的。不幸的是,如果没有任何锁定,您将无法确保在您要更新 map 时没有其他人正在阅读 map 。

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

  1. 获取“更新锁”互斥体。
  2. 复制 map 。您想要手动复制所有键/值:简单的赋值不起作用,因为映射是引用类型。
  3. 对 map 副本进行更改。
  4. 使用 sync/atomic 包中的 StorePointer 自动更新指向实时 map 的指针以指向您的新 map 。
  5. 释放互斥锁。

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

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

相关文章:

multithreading - 什么是过程交错? (在并发领域)

rest - beego 找不到 Controller

synchronization - MIPS 与锁同步

multithreading - 在Linux/UNIX上的多处理情况下是否可以使用互斥锁?

java - Tomcat并发

sql-server - sp_getapplock 同步对内存表的并发访问

performance - 测试并发性的基准问题

go - 无论如何在ansi控制台上打印斜体字体?

go - 为什么 IO.Writer 不填充接收器?

java - ConcurrentHashMap 上的同步是否正确?