Назад к вопросам
Middle+
1142
questionbank
Расскажите о паттерне управления конкурентностью (GMP) в языке Go.
Sobes Copilot
Получайте ответы в реальном времени
Ответ от нейросети
sobes.tech AI
GMP - это модель планирования выполнения горутин в Go, где:
- G (Goroutine): Легковесный поток выполнения, абстракция над системными потоками.
- M (Machine): Системный поток ОС. Может выполнять код одной или нескольких горутин.
- P (Processor): Логический процессор, представляющий контекст для выполнения горутин. Каждому P назначен M, и P содержит локальную очередь runnable горутин. Количество P по умолчанию равно
$GOMAXPROCS(обычно число ядер процессора).
Работает так:
- Планировщик (часть рантайма Go) ставит новые горутины в глобальную или локальные очереди P.
- M, связанный с P, забирает горутину из очереди P и выполняет её.
- Когда горутина блокируется (например, при ожидании I/O или на мьютексе):
- M отвязывается от текущего P.
- Планировщик пытается найти другой M, чтобы он занял этот P, или создаёт новый.
- Блокированная горутина ставится в специальную очередь.
- Когда блокировка снимается, горутина снова становится runnable и возвращается в очередь P.
- Когда горутина исчерпывает свой квант времени или явно уступает управление (редко), планировщик может переключить M на другую горутину в том же P.
Преимущества такого подхода:
- Эффективное использование системных потоков M.
- Снижение накладных расходов на переключение контекста по сравнению с нативными потоками ОС.
- Балансировка нагрузки между P за счет механизма "work stealing" (M может украсть горутину из очереди другого P).
Пример создания горутины:
// main.go
package main
import (
"fmt"
"time"
)
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second) // Иллюстрация блокировки/занятости
fmt.Printf("Worker %d finished\n", id)
}
func main() {
for i := 1; i <= 5; i++ {
go worker(i) // Создаем новую горутину
}
time.Sleep(time.Second * 2) // Ждем завершения горутин
}