Camada Zero · 10 · Deadlock & Starvation

Dois jeitos de uma goroutine parar de progredir. No deadlock todo mundo trava de vez por espera circular. Na starvation a goroutine está viva mas nunca é servida. Provoca os dois aqui embaixo e vê a diferença na tela.
Situação
0Goroutines bloqueadas
rodando bloqueada esperando / faminta terminou
Deadlock precisa das 4 condições de Coffman ao mesmo tempo. Quebrar qualquer uma já previne. O fix mais barato no dia a dia é matar a espera circular: todo mundo adquire os locks na mesma ordem global.
Condição de CoffmanComo quebrar
Exclusão mútuarecurso compartilhável / lock-free
Hold-and-waitpegar todos os locks de uma vez ou nenhum
Sem preempçãotimeout / TryLock e desistir
Espera circularordenação global de locks

O deadlock clássico em Go

var muA, muB sync.Mutex
// G1
go func() {
    muA.Lock()
    time.Sleep(time.Millisecond)
    muB.Lock() // espera B, que a G2 segura
    muB.Unlock(); muA.Unlock()
}()
// G2
go func() {
    muB.Lock()
    time.Sleep(time.Millisecond)
    muA.Lock() // espera A, que a G1 segura
    muA.Unlock(); muB.Unlock()
}()
// fatal error: all goroutines are asleep - deadlock!

O fix: ordenação de locks

// regra: SEMPRE A antes de B, nas duas goroutines
func work(muA, muB *sync.Mutex) {
    muA.Lock()
    muB.Lock()
    // seção crítica
    muB.Unlock()
    muA.Unlock()
}

🧠 Desafio — Deadlock & Starvation

Roda os cenários aqui de cima antes de responder. As duas últimas são de reflexão: escreve a sua e só então revela o modelo.