go - 你能让这个 'incorrectly synchronized' 测试失败吗?

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

最佳答案

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

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/

相关文章:

security - Go(更可能是go编译器)的内置功能是否可以解决二进制文件的篡改问题?

scala - Akka Actors 应该做真正的处理任务吗?

php - pfsockopen 线程安全?

json - 如何将 postgresql json 类型转换为 golang native?

go - 防止 go build 覆盖 go.mod 中的版本

java - 在迭代器内的线程内删除集合的元素

java - 如何在jsf中的bean中使用线程

java - Java中哪些情况需要同步方法访问?

mysql - 表 'test_db.colors'不存在

go - go web app 中句柄函数的代码设计