WaitGroup решит ожидание, но не гонку между тремя писателями map. Нужен также mutex для самих записей.
Синхронизация goroutine через sync.WaitGroup
WaitGroup решит ожидание, но не гонку между тремя писателями map. Нужен также mutex для самих записей.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В приведённом примере несколько горутин одновременно изменяют одну и ту же карту map[int]bool, что приводит к гонке данных. Чтобы гарантировать, что все изменения завершатся до того, как мы попытаемся прочитать значение из карты, необходимо воспользоваться sync.WaitGroup. Нужно добавить вызов Add() перед запуском горутин, вызвать Done() в конце каждой горутины и выполнить Wait() перед чтением карты. Укажите места вставки этих методов.
package main
import (
"fmt"
"time"
)
func main() {
data := make(map[int]bool)
go func() {
data[1] = true
}()
go func() {
data[1] = true
}()
go func() {
data[1] = false
}()
time.Sleep(1 * time.Second)
fmt.Printf("%v", data[1])
}
Ответ
WaitGroup решит ожидание, но не гонку между тремя писателями map. Нужен также mutex для самих записей.
Исправленный вариант:
package main
import (
"fmt"
"sync"
)
func main() {
data := make(map[int]bool)
var wg sync.WaitGroup
var mu sync.Mutex
for _, value := range []bool{true, true, false} {
wg.Add(1)
go func(value bool) {
defer wg.Done()
mu.Lock()
data[1] = value
mu.Unlock()
}(value)
}
wg.Wait()
fmt.Printf("%v", data[1])
}
Add вызывается до go, Done — внутри, Wait — перед чтением. После Wait писателей уже нет, поэтому финальное чтение не требует блокировки. Итог true или false зависит от последней записи: синхронизация устраняет гонку, но не задаёт порядок.