duanhao4909 2017-05-03 23:46
浏览 50
已采纳

甚至在golang中使用sync.Mutex时的比赛条件

Complete code is here: https://play.golang.org/p/ggUoxtcv5m go run -race main.go says there is a race condition there which I fail to explain. The program outputs correct final result, though.

The essence:

type SafeCounter struct {
    c int
    sync.Mutex
}

func (c *SafeCounter) Add() {
    c.Lock()
    c.c++
    c.Unlock()
}

var counter *SafeCounter = &SafeCounter{} // global

use *SafeCounter in incrementor:

func incrementor(s string) {
    for i := 0; i < 20; i++ {
        x := counter
        x.Add()
        counter = x
    }
}

The incrementor method is spawned twice in main:

func main() {
    go incrementor()
    go incrementor()
    // some other non-really-related stuff like
    // using waitGroup is ommited here for problem showcase
}

So, as I said, go run -race main.go will always say there is a race cond found.

Also, the final result is always correct (at least I've run this program for a number of times and it always say final counter is 40, which is correct). BUT, the program prints incorrect values in the beginning so you can get something like:

Incrementor1: 0 Counter: 2
Incrementor2: 0 Counter: 3
Incrementor2: 1 Counter: 4
// ang the rest is ok

so, printing out 1 is missing there.

Can somebody explain why there is a race condition there is my code?

  • 写回答

2条回答 默认 最新

  • doulingqiu4349 2017-05-04 00:21
    关注

    You have a number of race conditions, all pointed out specifically by the race detector:

        x := counter      // this reads the counter value without a lock
        fmt.Println(&x.c)
        x.Add()
        counter = x       // this writes the counter value without a lock
        time.Sleep(time.Duration(rand.Intn(3)) * time.Millisecond)
        fmt.Println(s, i, "Counter:", x.c) // this reads the c field without a lock
    
    • race #1 is between the read and the write of the counter value in incrementor

    • race #2 is between the concurrent writes to the counter value in incrementor

    • race #3 is between the read of the x.c field in fmt.Println, and the increment to x.c in the Add method.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 请问一下这个运行结果是怎么来的
  • ¥15 这个复选框什么作用?
  • ¥15 单通道放大电路的工作原理
  • ¥30 YOLO检测微调结果p为1
  • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下