Назад к вопросам
Middle
145
questionbank

Что такое starvation (голодание) в контексте многопоточности?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

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

Пример:

package main

import (
	"fmt"
	"sync"
	"time"
)

var (
	mu      sync.Mutex
	counter int
)

func worker(id int) {
	for {
		mu.Lock() // Защищаем ресурс (counter)
		// Здесь может возникнуть голодание, если другие горутины
		// постоянно будут захватывать мьютекс и удерживать его долго.
		counter++
		fmt.Printf("Работник %d увеличил счетчик до %d\n", id, counter)
		time.Sleep(10 * time.Millisecond) // Имитация работы
		mu.Unlock()
		// Добавим небольшую задержку, чтобы планировщик мог переключиться
		time.Sleep(1 * time.Millisecond)
	}
}

func main() {
	for i := 0; i < 5; i++ {
		go worker(i)
	}

	// Программа будет выполняться неограниченно долго,
	// но некоторые worker-ы могут испытывать голодание
	// в зависимости от планировщика и нагрузки.
	select {}
}

Для минимизации starvation применяются:

  • Справедливые блокировки (fair locks): Гарантируют, что потоки получают доступ к ресурсу в порядке запроса.
  • Randomness: Введение случайности в выбор потока, который получит доступ к ресурсу.
  • Timeouts: Установка ограничений по времени на ожидание ресурса.
  • Priority inversion avoidance: Избегание ситуаций, когда высокоприоритетный процесс ждет низкоприоритетный.

В Go стандартные мьютексы не гарантируют справедливости, что может привести к starvation при определенных условиях.