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()
}