【问题标题】:How can I find a data race in mutex-protected struct?如何在受互斥体保护的结构中找到数据竞争?
【发布时间】:2019-07-24 00:54:42
【问题描述】:

我有一个结构,其中包含一个可以从受互斥锁保护的不同 goroutine 访问的映射:

type Readings struct {
    sync.Mutex
    Timestamp time.Time
    values    map[meters.Measurement]float64
}

不过,它在Add(写入)和MarshalJSON(读取)之间存在数据竞争。后者进行结构转换:

func (r *Readings) Add(q QuerySnip) {
    r.Lock()
    defer r.Unlock()

    r.Timestamp = q.Timestamp
    if r.values == nil {
        r.values = make(map[meters.Measurement]float64)
    }

    r.values[q.Measurement] = q.Value
}

func (r *Readings) MarshalJSON() ([]byte, error) {
    r.Lock()
    defer r.Unlock()

    res := map[string]interface{}{
        "Timestamp": r.Timestamp,
        "Unix":      r.Timestamp.Unix(),
    }

    if r.values == nil {
        return json.Marshal(res)
    }

    for m, v := range r.values {
        res[m.String()] = v
    }

    return json.Marshal(res)
}

这是比赛:

WARNING: DATA RACE
Write at 0x00c000294900 by goroutine 11:
runtime.mapassign_fast64()
    /usr/local/opt/go/libexec/src/runtime/map_fast64.go:92 +0x0
github.com/volkszaehler/mbmd/server.(*Readings).Add()
    ...

Previous read at 0x00c000294900 by goroutine 25:
runtime.mapiterinit()
    /usr/local/opt/go/libexec/src/runtime/map.go:804 +0x0
github.com/volkszaehler/mbmd/server.(*Readings).MarshalJSON()
    /Users/andig/htdocs/mbmd/server/datagram.go:126 +0x304
github.com/volkszaehler/mbmd/server.(*data).MarshalJSON()
    ...

我不明白racey 在这里会发生什么,并且我无法复制将代码移动到独立测试用例中的竞争行为。

有进一步诊断的建议吗?

【问题讨论】:

  • 你确定不是每个 goroutine 都有一个指向结构的单独副本的指针吗?
  • 是否有可能两个Readings 共享同一个values 地图?
  • 都对。我复制了一个读数,在副本上调用 Add,在原件上调用 MarshalJson。这些值是共享的,本身没有被深度复制?
  • @andig:地图是参考值,它们不会被自动复制 (stackoverflow.com/questions/23057785/how-to-copy-a-map)
  • 如果您还复制了sync.Mutex,请注意第一次使用后无法复制互斥锁。 go vet 命令标记此错误。

标签: go


【解决方案1】:

两个cmets都是对的。我复制了一个读数,在副本上调用 Add,在原件上调用 MarshalJson。值是共享的,本身没有被深度复制。

【讨论】:

  • 这个答案本身并不是很有帮助,因为它只是重复了一条评论。我建议(1)关闭问题或(2)显着增强答案以显示导致问题的代码,以便其他人将来可以从中学习
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多