← Назад к вопросам

Что такое горутина? Сколько памяти она занимает?

2.3 Middle🔥 161 комментариев
#Конкурентность и горутины

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое горутина?

Горутина (goroutine) — это легковесный поток выполнения в языке программирования Go, реализованный на уровне рантайма. В отличие от системных потоков ОС (threads), которые требуют значительных ресурсов для создания и переключения контекста, горутины управляются планировщиком Go (scheduler) и выполняются в рамках ограниченного числа системных потоков. Это позволяет эффективно реализовать конкурентность (concurrency) — выполнять множество задач одновременно, не создавая избыточную нагрузку на систему.

Ключевые характеристики горутин:

  • Легковесность: Запуск требует минимум ресурсов по сравнению с потоками ОС.
  • Кооперативная многозадачность: Горутины добровольно уступают управление (через вызовы блокирующих операций или явные инструкции, как runtime.Gosched()), что снижает накладные расходы на переключение контекста.
  • Интеграция с каналами (channels): Горутины часто взаимодействуют через каналы, что является идиоматичным способом синхронизации и обмена данными в Go.
  • Простой запуск: Для запуска горутины используется ключевое слово go перед вызовом функции. Например:
    go func() {
        fmt.Println("Выполняется в горутине")
    }()
    

Горутины не являются потоками ОС — они абстрагированы от них. Планировщик Go динамически распределяет горутины по доступным потокам ОС (обычно их количество равно числу логических ядер CPU), обеспечивая эффективное использование ресурсов.

Сколько памяти занимает горутина?

Память, занимаемая горутиной, делится на два основных компонента: стек (stack) и дополнительные структуры данных в рантайме Go.

1. Изначальный размер стека

По умолчанию, горутина начинает с очень маленького стека, размер которого зависит от архитектуры:

  • 2 КБ на 32-битных системах.
  • 4 КБ на 64-битных системах.

Это значительно меньше стека потока ОС (который обычно составляет 1–8 МБ), что позволяет запускать десятки тысяч или даже миллионы горутин без исчерпания памяти. Например, запуск 1000 горутин с начальным стеком 4 КБ займет всего ~4 МБ памяти под стеки, в то время как 1000 потоков ОС потребовали бы гигабайты.

2. Динамическое изменение стека

Стек горутины динамически растет и сокращается по мере необходимости (технология segmented stacks или stack copying). Если горутине требуется больше памяти для вызовов функций или локальных переменных, рантайм автоматически увеличивает стек, обычно удваивая его размер. Это позволяет эффективно использовать память: стек не резервируется "на вырост", а адаптируется под реальные нужды.

3. Дополнительные накладные расходы

Помимо стека, каждая горутина имеет служебные структуры данных в рантайме Go для управления (например, информация для планировщика, каналы, defer-вызовы). Их размер обычно составляет несколько сотен байт. Точное значение зависит от версии Go и окружения, но в среднем общие накладные расходы на одну горутину оцениваются в ~2–8 КБ в типичных сценариях.

4. Практический пример

Рассмотрим простую программу, создающую 10 000 горутин:

package main

import (
    "fmt"
    "runtime"
    "time"
)

func main() {
    for i := 0; i < 10000; i++ {
        go func(id int) {
            time.Sleep(10 * time.Second)
        }(i)
    }
    // Выводим статистику памяти
    var m runtime.MemStats
    runtime.ReadMemStats(&m)
    fmt.Printf("Alloc = %v MiB\n", m.Alloc/1024/1024)
    runtime.Goexit()
}

На 64-битной системе такая программа может потреблять примерно 40–80 МБ оперативной памяти (зависит от активности горутин и сборщика мусора), что демонстрирует эффективность.

Ключевые факторы, влияющие на память:

  • Глубина рекурсии или вызовов функций: Может привести к росту стека.
  • Использование замыканий (closures) или больших локальных переменных: Увеличивает потребление стека.
  • Блокирующие операции: Горутины в ожидании (например, на каналах) всё равно занимают память, но их стек может быть частично освобожден.
  • Версия Go: В более новых версиях оптимизации могут снижать накладные расходы.

Итог

Горутина — это легковесная единица конкурентности с начальным стеком 2–4 КБ и динамическим изменением размера. Общие затраты памяти на одну горутину в простых случаях составляют несколько килобайт, что позволяет создавать сотни тысяч горутин на обычном оборудовании. Однако важно помнить, что реальное потребление зависит от логики программы — например, горутины, работающие с большими данными, будут использовать дополнительную память в куче (heap). Эффективное управление горутинами через каналы, контексты (context) и пулы воркеров помогает избегать утечек памяти и обеспечивать высокую производительность.

Что такое горутина? Сколько памяти она занимает? | PrepBro