Сначала скопируйте ключи, затем защищайте все записи одним mutex и дождитесь горутин до чтения map. Sleep не даёт гарантии отсутствия одновременного обхода или доступа.
Оптимизация и исправление конкурентного доступа к карте
Сначала скопируйте ключи, затем защищайте все записи одним mutex и дождитесь горутин до чтения map. Sleep не даёт гарантии отсутствия одновременного обхода или доступа.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Необходимо улучшить представленный код, устранив потенциальные проблемы при параллельных записях в общую структуру данных.
func main() {
m := map[string]int{
"one": 1,
"two": 2,
"three": 3,
"four": 4,
}
for key := range m {
key := key
go func() {
time.Sleep(time.Millisecond * 100)
m[key]++
}()
}
fmt.Println("Map after writes:", m)
}
Ответ
Сначала скопируйте ключи, затем защищайте все записи одним mutex и дождитесь горутин до чтения map. Sleep не даёт гарантии отсутствия одновременного обхода или доступа.
Нужны sync и fmt; искусственный Sleep не требуется:
keys := make([]string, 0, len(m))
for key := range m { keys = append(keys, key) }
var mu sync.Mutex
var wg sync.WaitGroup
for _, key := range keys {
wg.Add(1)
go func(key string) {
defer wg.Done()
mu.Lock()
m[key]++
mu.Unlock()
}(key)
}
wg.Wait()
fmt.Println("Map after writes:", m)
Значения станут one=2, two=3, three=4, four=5. Для такой небольшой операции последовательный цикл проще и обычно быстрее, но пример демонстрирует корректную синхронизацию.