你能让这个“错误同步”的测试失败吗?

时间:2017-08-27 17:34:56

标签: go concurrency

  1. 此测试是否可以在x86,x64,ARM上失败?
  2. 如果是这样,是否可以使其失败(在某种设置中)并且不更改测试代码本身?

    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.")
        }
    }
    

2 个答案:

答案 0 :(得分:0)

我已经改变了你的测试,以便在原子模块之间进行比较:

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(安培;条件,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只是为了清除这两种情况的区别。 但是为其他原子类型生成或多或少相同的代码,包括bool

如果你看一下i386平台上的原子/商店功能的实现,它实际上什么都不做:

同步/原子/ 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平台。另一件事是不好的做法 - 但实际上是另一张票的故事。

答案 1 :(得分:0)

它不能。见Does WaitGroup.Wait() imply memory barrier in this case?。非常感谢@OlegGolovanov查看了AS的ASM。