Могут ли процессы и потоки общаться между собой и как
Что проверяют
Различаете ли вы три уровня: процессы ОС, потоки ОС и горутины, и знаете ли, чем общаются на каждом. Следом обычно просят сравнить каналы и мьютексы или объяснить, как искать гонку данных.
Как отвечать
Процессы изолированы, у каждого своё адресное пространство, поэтому общаются они через ОС:
- пайпы:
os/execсcmd.StdinPipe()иcmd.StdoutPipe()для дочернего процесса; - сокеты: Unix-сокеты и TCP через пакет
net, поверх них HTTP или gRPC; - сигналы:
os/signal, типичный случай этоSIGTERMдля корректного завершения; - разделяемая память и файлы:
mmapчерезgolang.org/x/sys/unix, файлы с блокировками; - брокеры: Kafka, NATS, Redis, когда процессы живут на разных машинах.
Потоки внутри процесса делят память, но в Go вы работаете не с ними, а с горутинами. Рантайм раскладывает множество горутин на небольшое число потоков ОС по модели G-M-P, а число потоков, одновременно исполняющих Go-код, ограничено GOMAXPROCS.
Между горутинами:
- каналы: передача данных и владения, небуферизованный канал заодно синхронизирует отправителя и получателя;
sync.Mutexиsync.RWMutex: защита общего состояния вроде кэша;sync/atomic: одиночные счётчики и флаги;sync.WaitGroup,errgroup,context: ожидание, сбор ошибок и отмена;- семафор: буферизованный
make(chan struct{}, n)илиgolang.org/x/sync/semaphore.
Правило выбора: каналы для передачи данных и связи этапов, мьютекс для структуры, к которой обращаются многие. Обязательно назовите go test -race: детектор ловит несинхронизированный доступ во время выполнения.
Где спотыкаются
Называют горутины потоками и не могут объяснить разницу: стек горутины стартует с нескольких килобайт и растёт, а переключает их рантайм, а не ядро.
Пытаются связать каналами два процесса. Канал живёт в памяти одного процесса, между процессами нужен сокет, пайп или брокер.
Гоняют через каналы всё подряд, включая один счётчик, или не договариваются, кто закрывает канал. Итог: паника при записи в закрытый канал или фатальная ошибка all goroutines are asleep.