Почему Go не показывает переупорядочение памяти?
Я читаю пресессионный блог Переупорядочение памяти, замеченное в законе, и воспроизведенное переупорядочение памяти по его примеру кода
Тогда мне интересно, могу ли я воспроизвести переупорядочение памяти Go, поэтому я написал код примера в 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" ) отличается от С++ vs Go
-
Код сборки из С++
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
может препятствовать переупорядочению памяти
К настоящему моменту я не имею понятия о причине. Пожалуйста, помогите мне, спасибо.
Ответы
Ответ 1
Я не вижу вызова для установки GOMAXPROC в любом месте? Если вы его не назовете, вы будете работать только на одном CPU, который никогда не отобразит повторный порядок: http://golang.org/pkg/runtime/#GOMAXPROCS
Обновление: в Go 1.5 (выпущено 2015/08/19), а позже вам больше не нужно устанавливать GOMAXPROCS - Go по умолчанию для использования всех ваших процессоров.
Ответ 2
Модель памяти Go не относится к C или С++.
Посмотрите http://golang.org/ref/mem, в котором описывается отношение Happens Before" HB и как оно относится к каналам. Обратите внимание, что текущие реализации могут иметь больше HB, чем требуется для модели памяти.
Ответ 3
Я считаю, что инструкция mov ebx,[0x177f80]
делает разницу.
Он загружает ebx
, что означает, что mov [0x177f68],ebx
зависит от него и не может быть перемещен впереди него. Поэтому, если переупорядочение, оба перемещения, которые используют ebx
, должны быть переупорядочены вместе. Я думаю, что это не разрешено - архитектор x86_64 не переупорядочивает чтения с другими чтениями (на 100% не уверен).