В чем ключевые различия между стеком горутины и стеком системного потока (треда)?

Ответ

Стек горутины и стек системного потока (треда) кардинально различаются по размеру, управлению и влиянию на производительность.

Стек Горутины (Goroutine Stack):

  • Размер: Очень маленький, начинается всего с ~2 КБ.
  • Рост: Динамически расширяется и сжимается по мере необходимости. Этим управляет рантайм Go, копируя стек в новый, больший участок памяти при переполнении.
  • Управление: Полностью управляется средой выполнения Go (в user-space), а не операционной системой.
  • Переключение контекста: Очень быстрое и дешевое, так как не требует перехода в режим ядра (kernel mode). Планировщик Go сам решает, когда переключить горутину.

Стек Системного Потока (OS Thread Stack):

  • Размер: Большой и фиксированный (обычно от 1 до 8 МБ, в зависимости от ОС).
  • Рост: Не расширяется. Попытка использовать больше памяти, чем выделено, приводит к ошибке переполнения стека (stack overflow) и падению программы.
  • Управление: Управляется ядром операционной системы.
  • Переключение контекста: Медленное и дорогое, так как требует системного вызова и сохранения/восстановления большого контекста (регистры, состояние ядра и т.д.).

Ключевое следствие:
Благодаря легковесности горутин, в Go-приложении можно легко запустить сотни тысяч и даже миллионы горутин одновременно. Создание такого же количества системных потоков привело бы к исчерпанию памяти и краху системы.

func main() {
    // Запуск 100,000 горутин - стандартная практика в Go.
    for i := 0; i < 100000; i++ {
        go func() { /* какая-то работа */ }()
    }
    // Попытка создать 100,000 системных потоков почти наверняка
    // приведет к ошибке "out of memory".
}