【问题标题】:what does not being thread safe means about maps in Go?Go 中的地图不是线程安全的意味着什么?
【发布时间】:2015-07-30 17:47:52
【问题描述】:

我想知道当 go map 被多个 gooutins 访问时会发生什么让我们假设我们有一个map[int]*User。通过多个 goroutine 修改用户结构的字段会导致数据损坏吗?或者像 len() 这样的操作不是线程安全的,如果 map 在 Go 中是线程安全的会有什么不同?

【问题讨论】:

    标签: go


    【解决方案1】:

    同时修改*User 可能会导致map 的损坏不管。只要不修改映射,同时从映射中读取指针是安全的。修改*User指向的数据不会改变地图本身。

    同时修改map[int]*User 本身也有数据损坏的风险。

    没有良性数据竞争,请始终使用竞争检测器测试您的代码。

    【讨论】:

    • 我是否可以认为它是线程安全的,只使用锁来修改地图本身,而不是用户结构?
    • 可以,只要用户结构没有并发修改即可。
    【解决方案2】:

    最简单的例子;

    go WorkerMethodOne(myMapReference)
    go WorkerMethodTwo(myMapReference)
    

    在工作方法一中,我有一些这样的代码(示例)

    for i := 0; i < len(MyMapReference); i++ {
        if i % 2 == 0 {
           delete(MyMapReference, i)
        }
    }
    

    那么当 WorkerMethodTwo 迭代同一个映射并尝试访问刚刚被删除的项目时,会发生什么?虽然k, err := map[index] 可能仍然是安全的,但与您抛出的许多语言不同,它没有意义并且是不可预测的。最终可能会发生更糟糕的示例,例如尝试同时写入某些*User 的值。它可能会导致同时修改实际值(指针上的内容),或者您可以让指针从您下方拉出并随机使用与您预期不同的值等。这与让两个闭包作为 goroutine 运行并开始修改非原子 int 而不锁定/使用互斥锁并没有什么不同。你不知道会发生什么,因为在两个完全解耦的执行之间会争用该内存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-08
      • 2017-05-14
      • 2011-04-17
      • 1970-01-01
      • 1970-01-01
      • 2012-12-17
      • 1970-01-01
      相关资源
      最近更新 更多