Проверяет понимание потокобезопасности встроенной структуры map в Go и необходимости синхронизации.
Встроенная структура данных map в Go не предназначена для конкурентного доступа без дополнительной синхронизации. Это означает, что если несколько горутин одновременно читают и записывают в одну и ту же map, программа может завершиться с ошибкой fatal error: concurrent map writes или получить некорректные данные. Причина в том, что внутренняя реализация map не использует блокировки для обеспечения атомарности операций.
В Go конкурентность является ключевой особенностью, и часто разработчики используют горутины для параллельной обработки данных. Если не учитывать ограничения map, можно столкнуться с трудноуловимыми багами, которые проявляются только при высокой нагрузке. Поэтому важно знать, как правильно организовать доступ к общим данным.
Существует несколько подходов для безопасной работы с map в конкурентной среде:
sync.Mutex или sync.RWMutex для более эффективного чтения.sync.Map: специальная структура, оптимизированная для случаев, когда ключи стабильны или происходит много чтений.package main
import (
"fmt"
"sync"
)
type SafeMap struct {
mu sync.Mutex
m map[string]int
}
func NewSafeMap() *SafeMap {
return &SafeMap{m: make(map[string]int)}
}
func (s *SafeMap) Set(key string, value int) {
s.mu.Lock()
defer s.mu.Unlock()
s.m[key] = value
}
func (s *SafeMap) Get(key string) (int, bool) {
s.mu.Lock()
defer s.mu.Unlock()
val, ok := s.m[key]
return val, ok
}
func main() {
sm := NewSafeMap()
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
sm.Set(fmt.Sprintf("key%d", i), i)
}(i)
}
wg.Wait()
fmt.Println(sm.Get("key50"))
}package main
import (
"fmt"
"sync"
)
func main() {
var m sync.Map
var wg sync.WaitGroup
for i := 0; i < 100; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
m.Store(fmt.Sprintf("key%d", i), i)
}(i)
}
wg.Wait()
if val, ok := m.Load("key50"); ok {
fmt.Println(val)
}
}Используйте sync.Mutex или sync.RWMutex для защиты обычной map, когда требуется гибкость и контроль, или sync.Map для простых сценариев с частыми чтениями. Это обеспечит корректность и избежит паники в конкурентных программах.