Можно ли шарить данные между потоками
Что проверяют
Знаете ли вы, что общая память в Go разрешена, но безопасность обеспечиваете вы, а не рантайм. Одновременно смотрят, различаете ли вы канал как передачу владения и мьютекс как защиту общего состояния.
Как отвечать
Начать стоит с формулировки из документации: не общайтесь через общую память, делите память через общение. Это не запрет, а порядок предпочтения.
Три рабочих способа:
- канал: значение уезжает одной горутине, дальше с ним работает только она. Гонки нет, потому что нет одновременного доступа;
sync.Mutexиsync.RWMutex: общая структура остаётся на месте, доступ сериализуется.RWMutexвыигрывает только при заметном перевесе чтений, на коротких секциях он медленнее обычного мьютекса;sync/atomic, включая типы вродеatomic.Int64иatomic.Value: счётчики и флаги без блокировки.
Важно назвать модель памяти: без явной синхронизации запись одной горутины не гарантированно видна другой, даже если это простой bool. Компилятор и процессор вправе переупорядочивать операции, поэтому «просто переменная» не работает независимо от размера типа.
Практический довесок: гонки ловит детектор в go test -race и go run -race. Он не доказывает отсутствие гонки, но находит ту, что реально случилась на прогоне.
Где спотыкаются
Говорят «горутина это поток». Горутины мультиплексируются планировщиком рантайма на потоки операционной системы, их тысячи на нескольких потоках. Для вопроса это важно: даже при GOMAXPROCS=1 гонка возможна, потому что переключение происходит не там, где вы ожидаете.
Считают, что канал снимает все вопросы. Если по каналу уехал указатель или слайс, а отправитель продолжил писать в ту же память, гонка на месте. Передавать надо владение, то есть после отправки к объекту не прикасаться.
Защищают мьютексом запись, а чтение оставляют голым. Гонка это пара конкурентных обращений, где хотя бы одно на запись, поэтому под замком должны быть все обращения к полю. Рядом живёт частая мелочь: копирование структуры с мьютексом внутри, после чего копии блокируют разные замки. Про это предупреждает go vet.