跨 goroutines 共享内存

Go 中的以下测试失败:


type A struct {

    b bool

}


func TestWG(t *testing.T) {

    var wg sync.WaitGroup

    a := update(&wg)

    wg.Wait()

    if !a.b {

       t.Errorf("error")

    }

}


// Does not work

func update(group *sync.WaitGroup) A {

    a := A{

        b : false,

    }

    group.Add(1)

    go func() {

        a.b = true

        group.Done()

    }()

    return a

}

最初我认为这可能是由于没有障碍而发生的waitGroup.Done(),这可能解释了为什么update改为


// works

func update(group *sync.WaitGroup) A {

    a := A{

        b : false,

    }

    group.Add(1)

    go func() {

        a.b = true

        group.Done()

    }()

    time.Sleep(1*time.Second)

    return a

}

作品。但是然后将返回类型更改为pointer也可以使其工作


// works

func update(group *sync.WaitGroup) *A {

    a := A{

        b : false,

    }

    group.Add(1)

    go func() {

        a.b = true

        group.Done()

    }()

    return &a

}

有人能告诉我这里发生了什么吗?



泛舟湖上清波郎朗
浏览 158回答 1
1回答

jeck猫

您的第一个示例有数据竞赛!您返回a需要读取它的内容,并发 goroutine(您刚刚启动)在不同步的情况下写入它。所以输出是未定义的!go test -race也证实了这一点。time.Sleep()添加睡眠时也会发生同样的事情:数据竞争仍然存在(不是同步工具),因此结果仍然未定义!go test -race再次证实了这一点。当您将返回类型更改为指针时,您只需返回一个a不涉及读取值的a指针,并且启动的 goroutine 不会修改指针,只是指向的值。并且调用者TestWG()正确地等待直到它使用等待组完成,所以这里不会发生数据竞争。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go