#go #concurrency #happens-before #data-race
#Вперед #параллелизм #происходит -перед #гонка данных
Вопрос:
Недавно я обнаружил, что некоторый код выглядит следующим образом:
var m map[int]int
func writem() {
tmpm := make(map[int]int)
for i := 0; i < 4000000; i {
tmpm[i] = i 10
}
m = tmpm
}
func readm() {
for k, v := range m {
_, _ = k, v
}
}
func main() {
writem()
go readm()
writem()
}
Эта программа работает нормально, но я думаю, что writem
тело функции может быть переупорядочено путем перемещения m = tmpm
перед циклом for, потому что это не меняет поведение внутри этой подпрограммы. И это изменение порядка вызовет concurrent map read and map write
проблему. Как гласит модель памяти Go:
компиляторы и процессоры могут изменить порядок операций чтения и записи, выполняемых в рамках одной подпрограммы, только в том случае, если изменение порядка не изменяет поведение в рамках этой подпрограммы, как определено спецификацией языка
Я прав, или писать подобный код безопасно?
Комментарии:
1. Приведенная вами аннотация не применима к вашей ситуации, поскольку операции чтения и записи не выполняются в одной и той же подпрограмме. Итак, я не совсем понимаю ваш вопрос.
Ответ №1:
Эта программа работает нормально.
Нет, это не так.
Результаты программы не определены. У вас гонка данных на карте m
.
$ go run -race racer.go
==================
WARNING: DATA RACE
Write at 0x000000510fa0 by main goroutine:
main.writem()
/home/peter/gopath/src/racer.go:10 0xa7
main.main()
/home/peter/gopath/src/racer.go:22 0x4c
Previous read at 0x000000510fa0 by goroutine 13:
[failed to restore the stack]
Goroutine 13 (finished) created at:
main.main()
/home/peter/gopath/src/racer.go:21 0x47
==================
Found 1 data race(s)
exit status 66
$
racer.go
:
package main
var m map[int]int
func writem() {
tmpm := make(map[int]int)
for i := 0; i < 4000000; i {
tmpm[i] = i 10
}
m = tmpm
}
func readm() {
for k, v := range m {
_, _ = k, v
}
}
func main() {
writem()
go readm()
writem()
}
Игровая площадка: https://play.golang.org/p/OcWmK7ioMkD
Ссылка: Go: Детектор гонки данных