繁体   English   中英

在地图[string] int上使用sync.Mutex进行的Golang竞赛

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM