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

Как распределятся 4 горутины при их запуске на четырех ядрах

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

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

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

Горутины — это легковесные потоки выполнения в языке программирования Go. Они позволяют выполнять функции параллельно и асинхронно, что делает их мощным инструментом для создания конкурентных программ. Когда вы запускаете горутины, Go использует свой планировщик для управления их выполнением.

Планировщик Go

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

Распределение горутин

Когда вы запускаете 4 горутины на системе с четырьмя ядрами, планировщик Go может распределить их следующим образом:

  1. Назначение горутин ядрам: Каждая из 4 горутин может быть назначена на отдельное ядро. Это возможно, если планировщик решит, что это оптимально для выполнения задачи. Однако, это не гарантируется, так как планировщик может перемещать горутины между ядрами для более эффективного использования ресурсов.

  2. Перемещение горутин: Планировщик может перемещать горутины между ядрами в зависимости от нагрузки и других факторов, таких как блокировка ввода-вывода или ожидание других горутин. Это позволяет более эффективно использовать процессорное время и ресурсы.

Пример кода

package main
​
import (
	"fmt"
	"runtime"
	"sync"
)
​
func main() {
	runtime.GOMAXPROCS(4) // Устанавливаем максимальное количество процессоров, которые могут выполняться одновременно
​
	var wg sync.WaitGroup
	wg.Add(4) // Устанавливаем количество горутин, которые мы будем ожидать
​
	for i := 0; i < 4; i++ {
		go func(id int) {
			defer wg.Done() // Уменьшаем счетчик ожидания, когда горутина завершает выполнение
			fmt.Printf("Горутина %d выполняется\n", id)
		}(i)
	}
​
	wg.Wait() // Ожидаем завершения всех горутин
}
  • runtime.GOMAXPROCS(4): Устанавливает максимальное количество процессоров, которые могут выполняться одновременно. В данном случае, это 4, что соответствует количеству ядер.
  • var wg sync.WaitGroup: Создает группу ожидания для синхронизации завершения горутин.
  • wg.Add(4): Устанавливает количество горутин, которые мы будем ожидать.
  • go func(id int) { ... }(i): Запускает анонимную функцию как горутину, передавая ей идентификатор i.
  • defer wg.Done(): Уменьшает счетчик ожидания, когда горутина завершает выполнение.
  • fmt.Printf("Горутина %d выполняется\n", id): Выводит сообщение о выполнении горутины.
  • wg.Wait(): Ожидает завершения всех горутин.

Заключение

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

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

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

Твои заметки