Ответ
В Go используется гибридная модель многозадачности, сочетающая кооперативную и вытесняющую многозадачность, реализованная на основе модели M:N.
- Модель M:N: Рантайм Go распределяет M горутин (goroutines) для выполнения на N потоках операционной системы (OS threads). Обычно N равно количеству ядер CPU.
Планировщик Go управляет горутинами, используя два подхода:
Кооперативная многозадачность (Cooperative Multitasking):
- Горутина добровольно уступает процессорное время другой горутине.
- Это происходит в "безопасных точках": при блокирующих системных вызовах (I/O), операциях с каналами, мьютексами или при явном вызове
runtime.Gosched()
.
Вытесняющая многозадачность (Preemptive Multitasking):
- Начиная с Go 1.14, планировщик может принудительно прервать горутину, которая выполняется слишком долго без добровольной уступки (например, в долгих циклах без блокировок).
- Это решает проблему, когда одна вычислительно-интенсивная горутина могла монополизировать поток ОС, вызывая "голодание" других горутин.
- Механизм основан на асинхронных сигналах, которые рантайм посылает потоку, чтобы проверить состояние горутин и при необходимости переключить контекст.
func main() {
// Эта горутина будет вытеснена планировщиком,
// если будет работать слишком долго без блокировок.
go func() {
for {
// Длительные вычисления
}
}()
// Эта горутина добровольно уступит управление.
go func() {
fmt.Println("Уступаю очередь...")
runtime.Gosched()
}()
// ...
}