Когда потоки забирают горутины из глобальной очереди
1️⃣ Как кратко ответить
Потоки забирают горутины из глобальной очереди, когда локальные очереди потоков пусты. Это происходит для балансировки нагрузки между потоками и обеспечения эффективного использования ресурсов.
2️⃣ Подробное объяснение темы
В языке программирования Go горутины — это легковесные потоки, которые позволяют выполнять функции параллельно. Управление этими горутинами осуществляется планировщиком Go, который распределяет горутины между операционными системными потоками.
Как работает планировщик Go
Планировщик Go использует модель M:N, где M — это количество горутин, а N — количество операционных системных потоков. Основные компоненты планировщика:
- M (Machine): представляет собой операционный системный поток.
- P (Processor): логический процессор, который выполняет горутины. Количество P определяется переменной
GOMAXPROCS. - G (Goroutine): сама горутина, которая выполняется.
Локальные и глобальная очереди
Каждый логический процессор (P) имеет свою локальную очередь горутин. Когда горутина создается, она помещается в локальную очередь того P, который ее создал. Однако, если локальная очередь P становится пустой, поток, связанный с этим P, начинает забирать горутины из глобальной очереди.
Когда потоки забирают горутины из глобальной очереди
-
Пустая локальная очередь: Если локальная очередь P становится пустой, поток, связанный с этим P, обращается к глобальной очереди за новыми горутинами. Это позволяет равномерно распределять нагрузку между всеми доступными потоками.
-
Балансировка нагрузки: Глобальная очередь служит для балансировки нагрузки. Если один P перегружен, а другой простаивает, горутины могут быть перемещены из глобальной очереди в менее загруженные P.
-
Эффективное использование ресурсов: Забирание горутин из глобальной очереди позволяет эффективно использовать все доступные системные ресурсы, минимизируя время простоя потоков.
Пример кода
package main
import (
"fmt"
"runtime"
"sync"
)
func main() {
runtime.GOMAXPROCS(2) // Устанавливаем количество логических процессоров
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
fmt.Println("Горутина 1")
}()
go func() {
defer wg.Done()
fmt.Println("Горутина 2")
}()
wg.Wait()
}
runtime.GOMAXPROCS(2): Устанавливает количество логических процессоров, которые могут одновременно выполнять горутины. Это влияет на количество P.sync.WaitGroup: Используется для ожидания завершения всех горутин.go func() { ... }(): Создает и запускает новую горутину.
В этом примере, если бы у нас было больше горутин, чем логических процессоров, планировщик мог бы использовать глобальную очередь для распределения горутин между потоками, чтобы обеспечить их выполнение.
🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!
Подписаться