[英]Golang race with sync.Mutex on map[string]int
我有一个简单的程序包,用于在程序运行期间记录统计信息,但我发现go run -race
表示其中存在竞争条件。 看程序,我不确定每次互斥保护读和写时如何出现竞争状态。 有人可以解释吗?
package counters
import "sync"
type single struct {
mu sync.Mutex
values map[string]int64
}
// Global counters object
var counters = single{
values: make(map[string]int64),
}
// Get the value of the given counter
func Get(key string) int64 {
counters.mu.Lock()
defer counters.mu.Unlock()
return counters.values[key]
}
// Incr the value of the given counter name
func Incr(key string) int64 {
counters.mu.Lock()
defer counters.mu.Unlock()
counters.values[key]++ // Race condition
return counters.values[key]
}
// All the counters
func All() map[string]int64 {
counters.mu.Lock()
defer counters.mu.Unlock()
return counters.values // running during write above
}
我像这样使用包:
counters.Incr("foo")
counters.Get("foo")
一个最小的完整可验证示例在这里很有用,但是我认为您的问题出在All()
:
// All the counters
func All() map[string]int64 {
counters.mu.Lock()
defer counters.mu.Unlock()
return counters.values // running during write above
}
这将返回一个不复制它的map
,因此可以在互斥锁的保护范围之外对其进行访问。
All
返回基础映射并释放锁,因此使用该映射的代码将发生数据竞争。
您应该返回地图的副本:
func All() map[string]int64 {
counters.mu.Lock()
defer counters.mu.Unlock()
m := make(map[string]int64)
for k, v := range counters.values {
m[k] = v
}
return m
}
还是没有All
方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.