Проверяет понимание проблем конкурентного доступа к map в Go и необходимости синхронизации.
В 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.
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, оптимизированный для таких сценариев.