Оптимизация и исправление конкурентного доступа к карте

Сначала скопируйте ключи, затем защищайте все записи одним 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. Для такой небольшой операции последовательный цикл проще и обычно быстрее, но пример демонстрирует корректную синхронизацию.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее