Sobes.tech
Middle

O que é starvation (fome) no contexto de multithreading?

sobes.tech IA

Resposta da IA

Estado em que um ou mais goroutines (threads, processos) nunca acessam um recurso (por exemplo, um mutex, um canal) que precisam para continuar a execução, enquanto outros goroutines acessam constantemente esse recurso. Isso ocorre devido a um agendamento injusto ou mecanismos de sincronização ineficazes, como prioridades ou retenções excessivas de bloqueios.

Exemplo:

package main

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

var (
	mu      sync.Mutex
	counter int
)

func worker(id int) {
	for {
		mu.Lock() // Protegendo o recurso (counter)
		// Aqui pode ocorrer fome se outras goroutines
		// constantemente capturarem o mutex e o manterem por muito tempo.
		counter++
		fmt.Printf("Trabalhador %d aumentou o contador para %d\n", id, counter)
		time.Sleep(10 * time.Millisecond) // Simulação de trabalho
		mu.Unlock()
		// Adiciona uma pequena pausa para que o escalonador possa trocar de contexto
		time.Sleep(1 * time.Millisecond)
	}
}

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

	// O programa será executado indefinidamente,
	// mas alguns workers podem experimentar fome
	// dependendo do escalonador e da carga.
	select {}
}

Para minimizar o starvation, aplicam-se:

  • Locks justos (fair locks): Garantem que os threads acessem o recurso na ordem de solicitação.
  • Aleatoriedade: Introdução de aleatoriedade na escolha do thread que terá acesso ao recurso.
  • Timeouts: Definição de limites de tempo para esperar pelo recurso.
  • Prevenção de inversão de prioridade: Evitar situações em que um processo de alta prioridade espera por um de baixa prioridade.

Em Go, mutexes padrão não garantem justiça, o que pode levar ao starvation em certas condições.