Почему горутина в Go считается легковесным потоком и чем она отличается от потоков в других языках
Что проверяют
Понимаете ли вы, за счёт чего горутина дешевле потока ОС, и помните ли, что исполняется она всё равно на потоке. Следом обычно просят рассказать про планировщик и GOMAXPROCS или сравнить горутины с виртуальными потоками Java.
Как отвечать
Горутина это функция, исполнением которой управляет рантайм Go, а не ядро. Отсюда отличия:
- стек: стартует с 2 КБ и растёт копированием по мере надобности. Поток ОС получает фиксированный стек, на Linux обычно 8 МБ виртуальной памяти. Поэтому миллион горутин реален, а миллион потоков нет;
- создание и переключение:
go f()это постановка небольшой структуры в очередь рантайма, без системного вызова. Переключение идёт в пространстве пользователя, десятки наносекунд против примерно микросекунды у ядра; - планировщик GMP: G это горутина, M это поток ОС, P это логический процессор. Число P задаёт
GOMAXPROCS, по умолчанию равный количеству ядер, а с Go 1.25 рантайм учитывает и лимит CPU в cgroup контейнера. У каждого P своя очередь, свободный P крадёт работу у соседей, а сетевой ввод-вывод уходит в netpoller: горутина снимается с потока, а не занимает его; - вытеснение: с Go 1.14 планировщик вытесняет горутины асинхронно, сигналом, поэтому счётный цикл без вызовов функций больше не подвешивает P. Называть модель кооперативной сегодня неверно;
- взаимодействие: каналы и
selectвместо ручных примитивов, хотяsync.Mutexиatomicникуда не делись, а гонки ищетgo test -race.
Про другие языки честнее сказать, что подход не уникален: в Java с JDK 21 есть виртуальные потоки, в C# ту же роль играют async и await. Своеобразие Go в том, что модель одна и функции не делятся на обычные и асинхронные.
Где спотыкаются
Заучивают формулу «горутина это лёгкий поток» и не могут объяснить, что за ней стоит поток ОС и настоящий параллелизм на нескольких ядрах.
Считают горутины бесплатными и плодят их без ограничений. Горутина, навсегда заблокированная на канале, это классическая утечка: лечится отменой через context и ограничением пула.
Утверждают, что каналы отменяют синхронизацию. Общая память под мьютексом нередко быстрее и понятнее, а сам канал от гонки по данным не спасает.