有各种具有不同属性的任务执行器,其中一些仅支持非阻塞调用。因此,我在想,是否需要使用互斥锁/通道来安全地将任务结果传递给调用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] 删除。
我来说两句