Логотип YeaHub

База вопросов

Собеседования

Тренажёр

База ресурсов

Обучение

Навыки

Задачи

Войти

Выбери, каким будет IT завтра — вместе c нами!

YeaHub — это полностью открытый проект, призванный объединить и улучшить IT-сферу. Наш исходный код доступен для просмотра на GitHub. Дизайн проекта также открыт для ознакомления в Figma.

© 2026 YeaHub

AI info

Карта сайта

Документы

Медиа

Назад
Вопрос про Golang: Go, map, concurrency, race condition, sync.Mutex

Что произойдёт при конкурентной записи и чтении в обычную map без синхронизации?

Проверяет понимание проблем конкурентного доступа к map в Go и необходимости синхронизации.

Короткий ответ

При одновременной записи и чтении в map из разных горутин возникает состояние гонки (race condition). Go детектирует это и вызывает панику с сообщением "concurrent map read and map write". Это происходит потому, что map не является потокобезопасной структурой данных. Для безопасного доступа нужно использовать sync.Mutex или sync.RWMutex.

Длинный ответ

Проблема конкурентного доступа к map

В Go обычная map не предназначена для одновременного использования из нескольких горутин без синхронизации. Когда одна горутина пишет данные, а другая читает, внутренняя структура map может быть повреждена. Go runtime детектирует эту ситуацию и аварийно завершает программу с паникой.

Пример кода с ошибкой

package main

import (
	"fmt"
	"sync"
)

func main() {
	m := make(map[int]int)
	var wg sync.WaitGroup

	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 0; i < 1000; i++ {
			m[i] = i // запись
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < 1000; i++ {
			_ = m[i] // чтение
		}
	}()
	wg.Wait()
	fmt.Println("done")
}

Этот код вызовет панику: fatal error: concurrent map read and map write.

Правильное решение с sync.Mutex

package main

import (
	"fmt"
	"sync"
)

type SafeMap struct {
	mu sync.Mutex
	m  map[int]int
}

func (s *SafeMap) Set(key, value int) {
	s.mu.Lock()
	defer s.mu.Unlock()
	s.m[key] = value
}

func (s *SafeMap) Get(key int) int {
	s.mu.Lock()
	defer s.mu.Unlock()
	return s.m[key]
}

func main() {
	sm := SafeMap{m: make(map[int]int)}
	var wg sync.WaitGroup

	wg.Add(2)
	go func() {
		defer wg.Done()
		for i := 0; i < 1000; i++ {
			sm.Set(i, i)
		}
	}()
	go func() {
		defer wg.Done()
		for i := 0; i < 1000; i++ {
			_ = sm.Get(i)
		}
	}()
	wg.Wait()
	fmt.Println("done safely")
}

Использование мьютекса гарантирует, что только одна горутина имеет доступ к map в любой момент времени.

Вывод

Для безопасной работы с map в многопоточной среде всегда используйте sync.Mutex или sync.RWMutex. Если требуется высокая производительность при частых чтениях, рассмотрите sync.Map, оптимизированный для таких сценариев.

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.

Уровень

  • Рейтинг:

    4

  • Сложность:

    5

Навыки

  • Golang

    Golang

Ключевые слова

#Go

#map

#concurrency

#race condition

#sync.Mutex

Подпишись на Golang Developer в телеграм

  • Аватар

    Golang Guru

    Maxim Lukyanov

    Guru – это эксперты YeaHub, которые помогают развивать комьюнити.