- 此测试是否会在 x86、x64、ARM 上失败?
如果是这样,是否可以在不更改测试代码本身的情况下使其失败(在某种设置中)?
func Test_WaitGroup_Simple(t *testing.T) { var condition bool var wg sync.WaitGroup wg.Add(1) go func() { condition = true wg.Done() }() wg.Wait() if !condition { t.Error("Condition is false. But expected was true.") } }
最佳答案
我已经改变了你的测试以在原子模块之间进行比较:
package main
import (
"sync"
// "sync/atomic"
"fmt"
)
func main() {
var condition int32
var wg sync.WaitGroup
wg.Add(1)
go func() {
condition = 101
//atomic.StoreInt32(&condition,101)
wg.Done()
}()
wg.Wait()
if condition != 101 {
fmt.Println("Condition is false. But expected was true.")
} else {
fmt.Println("Ok.")
}
}
https://play.golang.org/p/8ewy2uMNNH
使用 go asm 我们可以检查将生成什么代码
go tool compile -S t.go
这里是内联代码的产生
atomic.StoreInt32(&condition,101)
0x001d 00029 (t.go:15) MOVL $101, AX
0x0022 00034 (t.go:15) MOVQ "".&condition+24(FP), CX
0x0027 00039 (t.go:15) XCHGL AX, (CX)
0x0029 00041 (t.go:16) MOVQ "".&wg+32(FP), AX
0x002e 00046 (t.go:16) MOVQ AX, (SP)
0x0032 00050 (t.go:16) PCDATA $0, $1
0x0032 00050 (t.go:16) CALL sync.(*WaitGroup).Done(SB)
这里是生产
条件 = 101
0x001d 00029 (t.go:14) MOVQ "".&condition+24(FP), AX
0x0022 00034 (t.go:14) MOVL $101, (AX)
0x0028 00040 (t.go:16) MOVQ "".&wg+32(FP), AX
0x002d 00045 (t.go:16) MOVQ AX, (SP)
0x0031 00049 (t.go:16) PCDATA $0, $1
0x0031 00049 (t.go:16) CALL sync.(*WaitGroup).Done(SB)
如您所见,代码并没有太大区别。我使用 int32 只是为了使这两种情况都变得不同。 但是 go 为包括 bool 在内的其他原子类型生成或多或少相同的代码
如果您查看 i386 平台上 atomic/store 函数的实现,它实际上什么都不做:
sync/atomic/asm_amd64.s
TEXT ·StoreUint32(SB),NOSPLIT,$0-8
MOVL addr+0(FP), BP
MOVL val+4(FP), AX
XCHGL AX, 0(BP)
RET
但是在32平台上存储64位已经很棘手了,当然不能用简单的“=”操作代替。
这就是为什么我的回答是:此测试将始终通过至少 386 和 amd64 平台。另一件事是这是一种不好的做法 - 但它实际上是另一张票的故事。
关于go - 你能让这个 'incorrectly synchronized' 测试失败吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45907588/