什么不是线程安全意味着Go中的地图?

时间:2015-07-30 17:47:53

标签: go

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

2 个答案:

答案 0 :(得分:3)

同时修改*User可能会导致损坏,而不管map。只要没有对地图进行修改,同时从地图中读取指针是安全的。修改数据*User指向不会对地图本身进行任何更改。

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

没有良性数据竞赛,总是使用竞赛检测器测试您的代码。

答案 1 :(得分:0)

最简单的例子;

go WorkerMethodOne(myMapReference)
go WorkerMethodTwo(myMapReference)

在worker方法一中,我有一些像这样的代码(例子)

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

然后当WorkerMethodTwo迭代同一个地图并尝试访问刚删除的项目时,会发生什么?虽然k, err := map[index]可能仍然是安全的,但与您投掷的许多语言不同,它没有意义且无法预测。最终会出现更糟糕的例子,例如尝试同时写入某些*User的值。它可能导致对实际值的并发修改(指针处的指针),或者您可以将指针从您的下方拉出来并随机使用与您预期的值不同的值。它实际上没有什么不同,如果您将两个闭包作为goroutines运行并开始修改非原子int而不锁定/使用互斥锁。你不会发生什么事情,因为两个完全解耦的执行之间存在争用的记忆。