这是一个正确的方法来使用并发读取更新全局的 Golang map 吗?

huangapple go评论79阅读模式
英文:

Is this a right way to update a global golang map with concurrent read?

问题

这是一个致命错误:并发地读取和写入映射的演示代码:

package main

var Map = make(map[int]int)

func main() {

	for i := 0; i < 100000; i++ {
		go updateMap()
		go readMap(i)
	}

}

func readMap(key int) int {
	return Map[key]
}

func updateMap() {
	for j := 0; j < 1000; j++ {
		Map[j] = j
	}
}

我没有使用锁或sync.Map,只是使用临时变量替换全局映射,这样就不会发生panic,代码如下:

package main

var Map = make(map[int]int)

func main() {

	for i := 0; i < 100000; i++ {
		go updateMap()
		go readMap(i)
	}

}

func readMap(key int) int {
	return Map[key]
}

func updateMap() {
	tmp := map[int]int{}
	for j := 0; j < 1000; j++ {
		tmp[j] = j
	}
	Map = tmp
}

这种更新全局映射的方式有问题吗?

英文:

this is a fatal error: concurrent map read and map write demo code:

package main

var Map = make(map[int]int)

func main() {

	for i := 0; i &lt; 100000; i++ {
		go updateMap()
		go readMap(i)
	}

}

func readMap(key int) int {
	return Map[key]
}

func updateMap() {
	for j := 0; j &lt; 1000; j++ {
		Map[j] = j
	}
}

I don't use the lock or sync.Map, just use tmp var to replace global map, it will not panic, codes like this:

package main

var Map = make(map[int]int)

func main() {

	for i := 0; i &lt; 100000; i++ {
		go updateMap()
		go readMap(i)
	}

}

func readMap(key int) int {
	return Map[key]
}

func updateMap() {
	tmp := map[int]int{}
	for j := 0; j &lt; 1000; j++ {
		tmp[j] = j
	}
	Map = tmp
}

Is there any problem with this way to update the global map?

答案1

得分: 1

更新地图的第二种方式不会引发恐慌,因为被更新的地图是一个临时地图,但仍然存在竞争条件。在updateMap函数之后,无法保证其他goroutine何时会看到updateMap的效果,如果有的话。

正确的方式是对两种情况都使用RWMutexreadMap应该使用RLock/RUnlock,而updateMap应该使用Lock/Unlock。对于第二种情况,如果updateMap是唯一更新地图的goroutine,你可以在复制阶段使用Rlock/RUnlock,在分配地图时使用Lock/Unlock

英文:

The second way of updating the map will not panic, because the map being updated is a temporary map, but there is still a race condition. After the updateMap function, there is no guarantee when the other goroutine will see the effects of updateMap, if ever.

The correct way is to use a RWMutex for both cases. The readMap should use RLock/RUnlock, and updateMap should use Lock/Unlock. For the second case, if the updateMap the only goroutine that ever updates the map, you can use Rlock/RUnlock during the copy phase, and Lock/Unlock when you assign the map.

huangapple
  • 本文由 发表于 2022年4月14日 11:58:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/71866358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定