为了账号安全,请及时绑定邮箱和手机立即绑定

跨 goroutines 共享内存

跨 goroutines 共享内存

Go
泛舟湖上清波郎朗 2022-07-11 10:22:04
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 workfunc update(group *sync.WaitGroup) A {    a := A{        b : false,    }    group.Add(1)    go func() {        a.b = true        group.Done()    }()    return a}最初我认为这可能是由于没有障碍而发生的waitGroup.Done(),这可能解释了为什么update改为// worksfunc 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也可以使其工作// worksfunc update(group *sync.WaitGroup) *A {    a := A{        b : false,    }    group.Add(1)    go func() {        a.b = true        group.Done()    }()    return &a}有人能告诉我这里发生了什么吗?
查看完整描述

1 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

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

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

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

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


查看完整回答
反对 回复 2022-07-11
  • 1 回答
  • 0 关注
  • 157 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号