c – 为什么Go不显示内存重新排序?

前端之家收集整理的这篇文章主要介绍了c – 为什么Go不显示内存重新排序?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在阅读preshing的博客 Memory Reordering Caught in the Act,并通过他的 example code再现记忆重新排序

然后我想知道我是否可以通过Go再现内存重新排序,所以我写了示例代码,但Go中没有显示内存重新排序.

我正在写信分享一些发现.

你能否帮助解释为什么Go不能获得记忆重新排序?谢谢.

Go中的示例代码

package main

    import (
            "fmt"
            "math/rand"
    )

    var x,y,r1,r2 int
    var detected = 0

    func randWait() {
            for rand.Intn(8) != 0 {
            }
    }

    func main() {
            beginSig1 := make(chan bool,1)
            beginSig2 := make(chan bool,1)
            endSig1 := make(chan bool,1)
            endSig2 := make(chan bool,1)
            go func() {
                    for {
                            <-beginSig1
                            randWait()
                            x = 1
                            r1 = y
                            endSig1 <- true
                    }
            }()
            go func() {
                    for {
                            <-beginSig2
                            randWait()
                            y = 1
                            r2 = x
                            endSig2 <- true
                    }
            }()
            for i := 1; ; i = i + 1 {
                    x = 0
                    y = 0
                    beginSig1 <- true
                    beginSig2 <- true
                    <-endSig1
                    <-endSig2
                    if r1 == 0 && r2 == 0 {
                            detected = detected + 1
                            fmt.Println(detected,"reorders detected after ",i,"iterations")
                    }
            }
    }

汇编代码(“ndisasm -b 32”)在C与Go之间显示不同

>来自C的汇编代码

00000CF0  C705520300000100  mov dword [0x352],0x1     //X=1
         -0000
00000CFA  8B0550030000      mov eax,[0x350]     
00000D00  89054E030000      mov [0x34e],eax      //r1=Y

> Go的汇编代码

000013EA  48                dec eax
000013EB  C70425787F170001  mov dword [0x177f78],0x1     //x=1
         -000000
000013F6  48                dec eax
000013F7  8B1C25807F1700    mov ebx,[0x177f80]
000013FE  48                dec eax
000013FF  891C25687F1700    mov [0x177f68],ebx          //r1=Y
00001406  48                dec eax

似乎Go在共享内存访问时使用dec eax,但是dec eax可以防止内存重新排序是没有意义的

> Intel® 64 and IA-32 Architectures Software Developer Manuals第3卷第8.2节显示了可能阻止记忆重新排序的情况,但不包括dec eax …
>我试图在C代码添加dec eax作为共享内存访问的余量,而内存重新排序仍然存在.

到现在为止,我并不知道这个原因.请帮我,谢谢.

解决方法

我没有看到任何地方设置GOMAXPROC?如果你不叫它,你将只运行一个cpu,不会显示重新排序: http://golang.org/pkg/runtime/#GOMAXPROCS

更新:在Go 1.5(发布2015/08/19)以后,您不再需要设置GOMAXPROCS – Go默认使用所有的cpu.

猜你在找的C&C++相关文章