在围棋程序中共享内存



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
}

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

您的第一个示例有一个数据竞赛!

您返回需要读取它的a,并发goroutine(您刚刚启动(在不同步的情况下写入它。所以输出是未定义的!CCD_ 5也证实了这一点。

添加睡眠时也会发生同样的情况:数据竞争仍然存在(time.Sleep()而不是同步工具(,因此结果仍然未定义!go test -race再次证实了这一点。

当您将返回类型更改为指针时,您只需返回一个指向a的指针,该指针不涉及读取a的值,并且启动的goroutine不会修改指针,只修改指向的值。调用方TestWG()使用waitgroup正确地等待,直到它完成,所以这里不会发生数据竞争。

相关内容

  • 没有找到相关文章

最新更新