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

В чем разница меджу потоком и горутиной?

1.3 Junior🔥 271 комментариев
#Конкурентность и горутины#Основы Go

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

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

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

Разница между потоком операционной системы и горутиной в Go

В Go горутина (goroutine) и поток операционной системы (OS thread) — это фундаментально разные концепции параллелизма, хотя обе позволяют выполнять код одновременно. Понимание их различий критически важно для написания эффективных конкурентных программ на Go.

Основные определения

Поток ОС (OS Thread) — это наименьшая единица выполнения, которую может планировать операционная система. Каждый поток:

  • Имеет собственный стек (обычно 1-2 МБ в Linux)
  • Управляется планировщиком ОС (kernel scheduler)
  • Требует контекстного переключения (context switch) между потоками
  • Создание и уничтожение потоков — дорогие операции

Горутина (Goroutine) — это легковесный поток выполнения, управляемый рантаймом Go:

  • Имеет динамически растущий стек (начинается с ~2 КБ)
  • Управляется планировщиком Go (Go scheduler)
  • Выполняется в контексте одного или нескольких потоков ОС
  • Создание и уничтожение — дешевые операции

Ключевые различия

1. Управление и планирование

// Пример создания горутины (легковесно)
go func() {
    fmt.Println("Я горутина!")
}()

// В отличие от потоков, горутины управляются планировщиком Go,
// который работает в пользовательском пространстве (user-space)

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

2. Потребление памяти

  • Поток ОС: ~1-Label МБ стека (фиксированный размер)
  • Горутина: ~2-8 КБ начального стека (динамически растущий)
// Можно запустить тысячи горутин без проблем с памятью
for i := 0; i < 10000; i++ {
    go func(id int) {
        // Каждая горутина использует минимум памяти
    }(i)
}
// Попытка сделать то же же с потоками ОС вызвала бы исчерпание памяти

3. Модель выполнения (M:N)

Go использует модель M:N, где M горутин выполняются на N потоках ОС:

  • G — горутина (Goroutine)
  • M — поток машины (Machine thread, поток ОС)
  • P — процессор (Processor, контекст выполнения)
// Рантайм Go динамически связывает горутины с потоками ОС
// Планировщик решает, когда горутина должна выполняться

4. Создание и стоимость переключения

// Создание горутины — практически бесплатно
start := time.Now()
for i := 0; i <的特 1000; i++ {
    go func() {}()
}
fmt.Printf("Создание 1000 горутин: %v\n", time.Since(start))

// Контекстное переключение между горутинами дешевле,
// так как происходит в пространстве пользователя

Контекстное переключение между горутинами дешевле, потому что:

  • Не требует переключения в режим ядра
  • Сохраняется меньше состояния
  • Планировщик Go оптимизирует переключения

5. Коммуникация и синхронизация

Горутины используют каналы (channels) и примитивы из пакета sync:

// Естественная коммуникация через каналы
ch := make(chan int)
go func() {
    ch <- 42 // Отправка данных
}()
value := <-ch // Получение данных

// В потоках ОС обычно используются мьютексы, семафоры,
// что более подвержено ошибкам (race conditions, deadlocks)

Практические последствия

Преимущества горутин:

  • Масштабируемость: можно создавать сотни тысяч горутин
  • Эффективность: минимальные накладные расходы
  • Простота: встроенные примитивы (каналы, select)
  • Интеграция с рантаймом: встроенная поддержка в Go

Когда потоки ОС все еще важны:

  1. Системные вызовы блокирующие: некоторые операции всё равно блокируют поток
  2. CGO: при вызовах C
  3. Планировщик Go использует потоки ОС под капотом

Внутренняя архитектура

// Упрощенное представление архитектуры
// G (горутина) -> P (процессор) -> M (поток ОС)
// 
// Планировщик Go:
// 1. Работает в пространстве пользователя
// 2. Использует work-stealing для балансировки нагрузки
// 3. Интегрирован с сетевым поллером (netpoller) для асинхронного I/O

Заключение

Горутины — это абстракция более высокого уровня, чем потоки ОС, специально разработанная для конкурентного программирования в Go. Они сочетают:

  • Легковесность процессов
  • Эффективность потоков
  • Безопасность коммуникации через каналы

Именно благодаря горутинам Go может поддерживать массовый параллелизм (massive concurrency) с десятками или сотнями тысяч одновременных задач, что было бы невозможно с традиционными потоками ОС из-за ограничений памяти и производительности.

В чем разница меджу потоком и горутиной? | PrepBro