Ответ
Это два фундаментальных подхода к управлению несколькими задачами в системе.
Кооперативная многозадачность (Cooperative Multitasking)
Задачи (процессы, потоки, горутины) должны добровольно отдавать управление планировщику. Если одна задача зависнет в долгом цикле без вызова специальной функции (условного yield()
), она заблокирует выполнение всех остальных задач.
- Плюсы: Простая реализация планировщика.
- Минусы: Ненадежность. Одна плохо написанная задача может "подвесить" всю систему.
Вытесняющая многозадачность (Preemptive Multitasking)
Планировщик (ОС или рантайм) может принудительно прервать выполнение задачи в любой момент, чтобы передать управление другой. Задаче не нужно "сотрудничать".
- Плюсы: Надежность и отзывчивость. Ни одна задача не может монополизировать процессор.
- Минусы: Более сложная реализация, требует механизма сохранения и восстановления контекста.
Реализация в Go
Планировщик Go прошел эволюцию:
-
До Go 1.14: Горутины использовали преимущественно кооперативную модель. Планировщик мог переключить контекст только в "безопасных точках" (safe points) — при вызовах функций, операциях с каналами, системных вызовах. Длинный цикл без таких вызовов (
for {}
) мог занять ядро на неопределенное время. -
С Go 1.14: Была добавлена асинхронная вытесняющая многозадачность. Теперь рантайм Go может принудительно остановить горутину, которая выполняется слишком долго (например, более 10 мс), даже если в ней нет вызовов функций. Это делает планировщик более справедливым и предотвращает "зависание" отдельных потоков ОС.