Что такое планирование горутин в Go и как оно работает?

Ответ

Планирование горутин в Go — это процесс управления выполнением множества горутин на ограниченном количестве потоков операционной системы. Этим занимается встроенный в рантайм Go планировщик (scheduler).

Ключевая модель: M, P, G

Планировщик Go использует модель M:P:G:

  • M (Machine): Поток операционной системы (OS Thread).
  • P (Processor): Логический процессор, представляет собой контекст для выполнения кода Go. Количество P по умолчанию равно количеству ядер CPU (runtime.GOMAXPROCS).
  • G (Goroutine): Сама горутина, легковесный поток.

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

Кооперативное вытеснение

Горутина уступает процессорное время в следующих случаях:

  • Системные вызовы: при блокирующих операциях ввода-вывода (например, работа с сетью или файлами).
  • Блокировка на каналах или мьютексах: когда горутина ждет данные или освобождения ресурса.
  • Вызов runtime.Gosched(): явное указание планировщику переключиться на другую горутину.
  • Длительные циклы: начиная с Go 1.14, планировщик может вытеснить горутину, которая выполняется слишком долго (более 10 мс) без точек переключения.

Также планировщик реализует механизм "воровства работы" (work-stealing): если у одного P заканчиваются горутины в очереди, он может "украсть" их у другого P, чтобы избежать простоя.