【问题标题】:Different output in race detector for println and fmt.Printlnprintln 和 fmt.Println 的竞争检测器中的不同输出
【发布时间】:2015-09-17 13:59:30
【问题描述】:

我无法解释比赛检测器中printlnfmt.Println 的不同输出。我预计两者都是种族,或者至少两者都不是种族。

package main

var a int

func f() {
    a = 1
}

func main() {
    go f()
    println(a)
}

而且,它会按预期找到竞争条件。

0
==================
WARNING: DATA RACE
Write by goroutine 5:
  main.f()
/home/felmas/test.go:6 +0x30

Previous read by main goroutine:
  main.main()
/home/felmas/test.go:11 +0x4d

Goroutine 5 (running) created at:
  main.main()
/home/felmas/test.go:10 +0x38
==================
Found 1 data race(s)

但是,这个运行时没有检测到任何种族。

package main

import "fmt"

var a int

func f() {
    a = 1
}

func main() {
    go f()
    fmt.Println(a)
}

据我所知,没有检测到种族并不意味着没有种族,所以这是这些缺陷之一还是有更深层次的解释,因为println 是内置的并且非常特别?

【问题讨论】:

  • 这只是偶然。比赛检测器没有看到比赛是 f() 没有执行。
  • @JimB 如果我添加time.Sleep 等待,仍然没有比赛并且输出为1 所以f 运行。
  • 我明白了。尽管您的测试不正确(并且 sleep 并不能保证 goroutine 会运行),但将值复制到接口中似乎有这种奇怪的行为。 (顺便说一句,比赛检测器只能保证没有误报,所以它偶尔会漏掉一些东西)
  • @JimB 你所说的睡眠是正确的,但在这里看到结果就足够了。我已经怀疑您对副本的解释,但想确保并看到正确的答案,以便我可以学到新的东西。误报,是的,最好检查种族,但我们不能承认没有种族。
  • 在此归档以供参考:golang.org/issue/12664

标签: go concurrency goroutine


【解决方案1】:

比赛检测器是一种动态测试工具,没有静态分析。为了从竞争检测器中获得可靠的结果,您应该争取对程序进行高测试覆盖率,最好使用多个进程编写大量benchmarks(通过设置 GOMAXPROCS > 1,GOMAXPROCS=NumCPU 是 Go 1.5 的默认值) 并使用定期执行这些测试的持续集成工具。

比赛检测器不会报告任何误报,因此您应该认真对待每个输出。另一方面,它可能不会在每次运行时检测到每场比赛,具体取决于 goroutine 和进程的调度顺序。

在您的示例中,将所有内容封装在一个紧密的循环中并重新执行测试在这两种情况下都正确报告了比赛。

【讨论】:

    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-02
    • 2021-01-07
    • 1970-01-01
    相关资源
    最近更新 更多