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

Где исполняются горутины?

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

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

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

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

Место исполнения горутин в Go

Горутины исполняются в контексте операционной системы (ОС), но управляются средой выполнения Go (runtime), которая представляет собой слой абстракции между кодом на Go и операционной системой. Конкретный ответ зависит от уровня рассмотрения: логическом, физическом и уровне управления.

Логический уровень: Модель многопоточности

На логическом уровне горутины исполняются в рамках модели M:N, где:

  • M — это множество горутин (пользовательские потоки, легковесные потоки).
  • N — это множество потоков ОС (системные потоки, часто называемые "нитками" или threads).

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

Физический уровень: Потоки операционной системы

В конечном итоге, код горутин выполняется на потоках операционной системы (POSIX-потоках на Unix/Linux, Windows-тредах на Windows), которые, в свою очередь, планируются на выполнение ядром ОС на доступных ядрах/процессорах CPU.

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

package main

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

func main() {
    // Узнаем количество логических процессоров, равное количеству потоков ОС по умолчанию
    fmt.Println("Логических процессоров (GOMAXPROCS):", runtime.GOMAXPROCS(0))

    for i := 0; i < 5; i++ {
        go func(id int) {
            // Бесконечная работа горутины
            for {
                fmt.Printf("Горутина %d жива\n", id)
                time.Sleep(time.Second)
            }
        }(i)
    }

    // Даем время на выполнение
    time.Sleep(3 * time.Second)
}

Уровень управления: Планировщик Go (Go Scheduler)

Сердце исполнения горутин — это планировщик Go (scheduler), работающий в кооперативно-вытесняющем режиме. Он отвечает за:

  1. Связывание горутин (G) с потоками ОС (M), которые выполняются на логических процессорах (P).
  2. Распределение готовых к выполнению горутин по свободным процессорам (P).
  3. Кооперативное переключение горутин в определенных точках (каналы, вызовы функций, runtime.Gosched()).
  4. Вытесняющее переключение (начиная с Go 1.14) при долгом занятии потока ОС одной горутиной.

Модель планировщика известна как модель GMP:

  • G (Goroutine) — сама горутина, её стек и состояние.
  • M (Machine) — поток операционной системы (thread).
  • P (Processor) — логический процессор, контекст для выполнения кода G. Он содержит локальную очередь готовых горутин.

Ключевые моменты реализации

  • Собственные стеки: Каждая горутина начинается с небольшого стека (несколько КБ), который динамически растет и сжимается в куче программы. Это позволяет создавать миллионы горутин, тогда как потоки ОС имеют фиксированный стек (часто 1-2 МБ).
  • Блокирующие вызовы: Если горутина выполняет блокирующий системный вызов (например, файловый ввод-вывод), планировщик может отвязать поток ОС (M) от процессора (P) и создать новый поток ОС для выполнения других горутин из очереди, чтобы не терять ресурсы CPU.
  • Сетевые операции: Для сетевого ввода-вывода Go использует асинхронные механизмы ОС (например, epoll на Linux, kqueue на BSD, IOCP на Windows). Горутина, ожидающая сетевых данных, приостанавливается, а её поток ОС используется для выполнения других задач. При поступлении данных среда выполнения "пробуждает" соответствующую горутину и ставит её в очередь на выполнение.

Итог

Таким образом, можно дать многослойный ответ:

  1. Абстрактно/логически: Горутины исполняются в виртуальном пространстве, управляемом планировщиком Go.
  2. Физически: Их машинный код в конечном счете выполняется на потоках операционной системы (threads), которые планируются на ядрах процессора.
  3. Архитектурно: Они живут в рамках модели GMP (Goroutine-Machine-Processor) внутри среды выполнения Go.

Эта многоуровневая архитектура, где тяжелые потоки ОС (M) отделены от легковесных единиц работы (G), позволяет Go эффективно использовать ресурсы системы, поддерживая высокий уровень конкурентности с минимальными накладными расходами на переключение контекста.

Где исполняются горутины? | PrepBro