Ответ
Горутины — это легковесные потоки исполнения, которые управляются не операционной системой, а средой выполнения (runtime) Go. Их ключевое преимущество — низкое потребление ресурсов (начальный размер стека ~2 КБ) и эффективное переключение контекста.
Модель планировщика M:P:G
В основе работы горутин лежит модель планировщика M:P:G:
- G (Goroutine): Сама горутина со своим стеком, указателем на текущую инструкцию и состоянием.
- M (Machine): Системный поток ОС (OS thread). Это реальный поток, который выполняет код.
- P (Processor): Контекст для выполнения Go-кода. Он представляет собой ресурс для запуска горутин и имеет локальную очередь горутин (LRQ), готовых к выполнению. Количество
P
по умолчанию равно количеству ядер CPU (GOMAXPROCS
).
Процесс работы: Планировщик Go стремится, чтобы на каждом системном потоке M
был запущен контекст P
, который, в свою очередь, выполняет горутины G
из своей локальной очереди. Это позволяет мультиплексировать тысячи горутин на небольшом количестве системных потоков.
Ключевые аспекты
- Запуск: Горутина создается с помощью ключевого слова
go
.go func() { fmt.Println("Я — горутина!") }()
- Конкурентность: Горутины выполняются конкурентно. Для достижения параллелизма (одновременного выполнения на разных ядрах)
GOMAXPROCS
должен быть больше 1. - Синхронизация: Для безопасного обмена данными между горутинами используются каналы (
chan
). Для синхронизации выполнения — примитивы из пакетаsync
(WaitGroup
,Mutex
). - Завершение: Если главная горутина (
main
) завершает свою работу, все остальные горутины принудительно останавливаются.