В приведённом коде обращения к map уже защищены общим RWMutex: чтение под RLock, запись под Lock. Гонка возможна, только если другие обращения обходят эту защиту.
Безопасный конкурентный доступ к глобальной карте
В приведённом коде обращения к map уже защищены общим RWMutex: чтение под RLock, запись под Lock. Гонка возможна, только если другие обращения обходят эту защиту.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В программе объявлена глобальная карта map[string]int, к которой одновременно обращаются несколько горутин: одна читает, другая записывает. При таком параллелизме возникает паника fatal error: concurrent map read and map write. Требуется выбрать подходящий механизм синхронизации, чтобы избавиться от гонки и обеспечить корректную работу программы.
package main
import (
"fmt"
"sync"
"time"
)
var (
mu sync.RWMutex
m = map[string]int{"a": 1}
)
func main() {
go read()
time.Sleep(1 * time.Second)
go write()
time.Sleep(1 * time.Second)
}
func read() {
for {
mu.RLock()
fmt.Println(m["a"])
mu.RUnlock()
}
}
func write() {
for {
mu.Lock()
m["a"] = 2
mu.Unlock()
}
}
Каким способом синхронизации (например, мьютекс, RWMutex, sync.Map, каналы и т.д.) следует решить проблему?
Ответ
В приведённом коде обращения к map уже защищены общим RWMutex: чтение под RLock, запись под Lock. Гонка возможна, только если другие обращения обходят эту защиту.
Улучшите жизненный цикл: бесконечные busy-loop и Sleep в main не дают управляемого завершения. Передавайте context и ждите работников; значение копируйте под RLock, а медленную печать делайте после RUnlock. Обычный Mutex тоже корректен и может быть проще. Выбор RWMutex, sync.Map или владельца-горутин зависит от нагрузки, а не от необходимости скрыть fatal error через recover.