【发布时间】:2015-07-30 17:47:52
【问题描述】:
我想知道当 go map 被多个 gooutins 访问时会发生什么让我们假设我们有一个map[int]*User。通过多个 goroutine 修改用户结构的字段会导致数据损坏吗?或者像 len() 这样的操作不是线程安全的,如果 map 在 Go 中是线程安全的会有什么不同?
【问题讨论】:
标签: go
我想知道当 go map 被多个 gooutins 访问时会发生什么让我们假设我们有一个map[int]*User。通过多个 goroutine 修改用户结构的字段会导致数据损坏吗?或者像 len() 这样的操作不是线程安全的,如果 map 在 Go 中是线程安全的会有什么不同?
【问题讨论】:
标签: go
同时修改*User 可能会导致map 的损坏不管。只要不修改映射,同时从映射中读取指针是安全的。修改*User指向的数据不会改变地图本身。
同时修改map[int]*User 本身也有数据损坏的风险。
没有良性数据竞争,请始终使用竞争检测器测试您的代码。
【讨论】:
最简单的例子;
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 而不锁定/使用互斥锁并没有什么不同。你不知道会发生什么,因为在两个完全解耦的执行之间会争用该内存。
【讨论】: