← Назад ко всем вопросам

Когда потоки забирают горутины из глобальной очереди

1️⃣ Как кратко ответить

Потоки забирают горутины из глобальной очереди, когда локальные очереди потоков пусты. Это происходит для балансировки нагрузки между потоками и обеспечения эффективного использования ресурсов.

2️⃣ Подробное объяснение темы

В языке программирования Go горутины — это легковесные потоки, которые позволяют выполнять функции параллельно. Управление этими горутинами осуществляется планировщиком Go, который распределяет горутины между операционными системными потоками.

Как работает планировщик Go

Планировщик Go использует модель M:N, где M — это количество горутин, а N — количество операционных системных потоков. Основные компоненты планировщика:

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

Локальные и глобальная очереди

Каждый логический процессор (P) имеет свою локальную очередь горутин. Когда горутина создается, она помещается в локальную очередь того P, который ее создал. Однако, если локальная очередь P становится пустой, поток, связанный с этим P, начинает забирать горутины из глобальной очереди.

Когда потоки забирают горутины из глобальной очереди

  1. Пустая локальная очередь: Если локальная очередь P становится пустой, поток, связанный с этим P, обращается к глобальной очереди за новыми горутинами. Это позволяет равномерно распределять нагрузку между всеми доступными потоками.

  2. Балансировка нагрузки: Глобальная очередь служит для балансировки нагрузки. Если один P перегружен, а другой простаивает, горутины могут быть перемещены из глобальной очереди в менее загруженные P.

  3. Эффективное использование ресурсов: Забирание горутин из глобальной очереди позволяет эффективно использовать все доступные системные ресурсы, минимизируя время простоя потоков.

Пример кода

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() { ... }(): Создает и запускает новую горутину.

В этом примере, если бы у нас было больше горутин, чем логических процессоров, планировщик мог бы использовать глобальную очередь для распределения горутин между потоками, чтобы обеспечить их выполнение.

Тема: Конкурентность
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки