Почему эта программа
func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func() {
fmt.Print(i)
wg.Done()
}()
}
wg.Wait()
fmt.Println()
}
печатает
55555
(WaitGroup ожидает завершения набора goroutine.)
Ответ
Существует гонка данных: переменная i совместно используется шестью (6) goroutine.
Гонка данных происходит, когда две goroutine обращаются к одной и той же переменной одновременно, и по крайней мере одно из обращений является записью.
Чтобы избежать этого, используйте локальную переменную и передайте число в качестве параметра при запуске goroutine.
func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(n int) { // Используем локальную переменную.
fmt.Print(n)
wg.Done()
}(i)
}
wg.Wait()
fmt.Println()
}
Пример вывода:
40123
Также возможно избежать этой гонки данных, все еще используя замыкание, но тогда мы должны позаботиться об использовании уникальной переменной для каждой goroutine.
func main() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
n := i // Создаем уникальную переменную для каждого замыкания.
go func() {
fmt.Print(n)
wg.Done()
}()
}
wg.Wait()
fmt.Println()
}
Читайте также:
- Анонимные функции и замыкания в Golang
- Гонки данных в Golang простыми словами
- Golang puzzlers: синхронизации go-процедур (goroutine)
Комментариев нет:
Отправить комментарий