从其他go例程使用WaitGroup阻止当前线程写入堆栈变量是否安全?

要求:

有各种具有不同属性的任务执行器,其中一些仅支持非阻塞调用。因此,我在想,是否需要使用互斥锁/通道来安全地将任务结果传递给调用go-routine,或者它是否足够简单WaitGroup

为了简单起见和问题的特殊性,使用非常幼稚的任务执行器启动函数直接作为go例程的示例:

func TestRace(t *testing.T) {
    var wg sync.WaitGroup

    a, b := 1, 2

    wg.Add(1)

    // this func would be passed to real executor
    go func() {
        a, b = a+1, b+1
        wg.Done()
    }()

    wg.Wait()

    assert.Equal(t, a, 2)
    assert.Equal(t, b, 3)
}

-race在我的机器上,执行带有option 的测试没有失败。但是,这足够保证吗?如果在不同的CPU内核,CPU内核块(AMD CCX)或多插槽设置的不同CPU上执行了例程,该怎么办?

因此,问题是,我可以WaitGroup用来为非阻塞执行程序提供同步(阻塞和返回值)吗?

星期二:

JimB或许应该提供这样的答案,但我会从复制他的 意见,开始与这一个

WaitGroup这里,以确保a, b = a+1, b+1已经执行,所以没有理由认为它没有。

[和]

保证您已经被go内存模型所布局,该模型 [ 此处 ] 有充分的文档说明[具体地说,在示例中wg.Done()的组合wg.Wait()足以保证对两个变量a和的非民主访问b

只要存在此问题,也可以复制Adrian的评论作为一个好主意

正如@JimB所指出的,如果goroutine之间共享一个值,则无法在堆栈中分配该值,因此这个问题尚无定论(请参阅Go闭包如何在内存中布置?)。WaitGroup正常工作。

关闭变量是堆分配的事实是一个实现细节:将来可能不正确。sync.WaitGroup保证仍然是真实的,今后,即使一些聪明进去以后编译器能够保持这些变量的一些堆栈。

(“哪个堆栈?”完全是另一个问题,但是假设的将来聪明的Go编译器可以回答这个问题。and WaitGroup内存模型提供了规则。)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章