douqiang6448 2019-04-02 07:29
浏览 48
已采纳

尚不存在的对象的竞争条件

I've a strange race condition. The problem is that it occurs inside an object which is not existing yet.

Here is a demo code:

package main

import (
    //"fmt"
    "time"
)

type Object1 struct {
    A int
    B string
    C []int
    D *Object2
}

type Object2 struct {
    A int
}

func NewObject1() *Object1 {
    return &Object1{
        A: 1,
        B: "abc",
        C: []int{0, 1},
        D: &Object2{},
    }
}

func main() {
    list := []*Object1{}

    tempA := 0
    tempB := ""
    tempC := []int{}
    tempD := &Object2{}

    go func() {
        for {
            for _, object := range list {
                tempA = object.A
                tempB = object.B
                tempC = object.C
                tempD = object.D
            }
        }
    }()

    for {
        list = append(list, NewObject1())

        //fmt.Println("list", list)
        time.Sleep(1 * time.Second)
    }
}

If I run it with the -race flag - I get the warnings:

WARNING: DATA RACE
Read at 0x00c000094040 by goroutine 5:
  main.main.func1()
      /tmp/race.go:39 +0x84

Previous write at 0x00c000094040 by main goroutine:
  main.main()
      /tmp/race.go:21 +0x2a9

Goroutine 5 (running) created at:
  main.main()
      /tmp/race.go:36 +0x276
==================
==================
WARNING: DATA RACE
Read at 0x00c000094048 by goroutine 5:
  main.main.func1()
      /tmp/race.go:40 +0xbe

Previous write at 0x00c000094048 by main goroutine:
  main.main()
      /tmp/race.go:22 +0x2ca

Goroutine 5 (running) created at:
  main.main()
      /tmp/race.go:36 +0x276
==================
==================
WARNING: DATA RACE
Read at 0x00c000094058 by goroutine 5:
  main.main.func1()
      /tmp/race.go:41 +0x118

Previous write at 0x00c000094058 by main goroutine:
  main.main()
      /tmp/race.go:23 +0x341

Goroutine 5 (running) created at:
  main.main()
      /tmp/race.go:36 +0x276
==================
==================
WARNING: DATA RACE
Read at 0x00c000094070 by goroutine 5:
  main.main.func1()
      /tmp/race.go:42 +0x180

Previous write at 0x00c000094070 by main goroutine:
  main.main()
      /tmp/race.go:24 +0x3b8

Goroutine 5 (running) created at:
  main.main()
      /tmp/race.go:36 +0x276
==================

But how is that possible? Reading happens inside a goroutine and writing inside a NewObject1(). 4 errors for every Object1 field. NewObject1() has not created an object yet to append it to the list slice. So list during the reading should be empty or filled with a normal completed objects.

Step by step workflow in my mind:

  1. list is empty;
  2. you start to create new object1;
  3. list is still empty;
  4. you have created a new object and only then add it to the list;
  5. only now list has 1 element;
  6. reading happens.

I don't see a race condition here. If you think differently - please show your own workflow of how things happens.

  • 写回答

1条回答 默认 最新

  • doushou7169 2019-04-02 08:17
    关注

    Race detector detects that you concurrently read and write the same address in memory.

    It is by definition a data race.

    It does not matter when data was actually put to that address (and whether it was put there at all). What only matters is that you access the same memory in different goroutines without synchronisation, and one of those operations is a "write".

    Both are not about Go, but are extremely quality resources:

    1. https://preshing.com/20120710/memory-barriers-are-like-source-control-operations/ - this and basically every other article in that blog is a gem.
    2. http://deadlockempire.github.io/ - a puzzle-like game that reveals nuances of synchronisation and concurrency issues
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 ansys fluent计算闪退
  • ¥15 有关wireshark抓包的问题
  • ¥15 需要写计算过程,不要写代码,求解答,数据都在图上
  • ¥15 向数据表用newid方式插入GUID问题
  • ¥15 multisim电路设计
  • ¥20 用keil,写代码解决两个问题,用库函数
  • ¥50 ID中开关量采样信号通道、以及程序流程的设计
  • ¥15 U-Mamba/nnunetv2固定随机数种子
  • ¥15 vba使用jmail发送邮件正文里面怎么加图片
  • ¥15 vb6.0如何向数据库中添加自动生成的字段数据。