Wat is een deadlock bij het werken met goroutine?
sobes.tech AI
Antwoord van AI
Deadlock (dode) is een situatie waarin twee of meer goroutines elkaar blokkeren door op elkaar te wachten, en geen van hen kan verder gaan met uitvoeren. Dit gebeurt meestal bij het werken met mutexen of kanalen.
Voorbeelden van deadlocks:
-
Mutexen in verschillende volgorde blokkeren:
// Voorbeeld van deadlock met mutexen var mu1 sync.Mutex var mu2 sync.Mutex func goroutine1() { mu1.Lock() // Blokkeert mu1 time.Sleep(100 * time.Millisecond) // Wacht even mu2.Lock() // Probeert mu2 te blokkeren (bezet door goroutine2) fmt.Println("goroutine1 verwierf mu2") mu2.Unlock() mu1.Unlock() } func goroutine2() { mu2.Lock() // Blokkeert mu2 time.Sleep(100 * time.Millisecond) // Wacht even mu1.Lock() // Probeert mu1 te blokkeren (bezet door goroutine1) fmt.Println("goroutine2 verwierf mu1") mu1.Unlock() mu2.Unlock() }Goroutine1 heeft mu1 veroverd en wacht op mu2. Goroutine2 heeft mu2 veroverd en wacht op mu1. Beiden zijn geblokkeerd.
-
Verzenden naar een niet-buffered kanaal zonder ontvanger:
// Voorbeeld van deadlock met kanaal func main() { ch := make(chan int) //go func() { // Als er geen goroutine wordt gestart om te lezen, ontstaat deadlock // <-ch //}() ch <- 1 // Verzenden naar kanaal zonder actieve ontvanger fmt.Println("Verzonden naar kanaal") // Deze regel wordt niet bereikt }Verzenden naar een niet-buffered kanaal blokkeert totdat een andere goroutine begint te lezen. Als er geen ontvanger is, ontstaat deadlock.
-
Lezen uit een kanaal zonder zender (na sluiting of met lege buffer):
// Voorbeeld van deadlock bij lezen uit kanaal func main() { ch := make(chan int, 1) // Bufferkanaal met 1 element ch <- 1 // Verzendt 1 close(ch) // Sluit kanaal <-ch // Leest 1 <-ch // Poging om opnieuw te lezen uit een gesloten en lege kanaal - deadlock }Lezen uit een gesloten en niet-lege kanaal zal succesvol zijn. Lezen uit een gesloten en lege kanaal of uit een open maar lege kanaal zonder zender leidt tot blokkering.
De Golang-runtime kan bepaalde soorten deadlocks detecteren (bijvoorbeeld wanneer alle geblokkeerde goroutines wachten op ontvangst of verzending door een enkele goroutine), en in dat geval stopt het programma abrupt met de melding "fatal error: all goroutines are asleep - deadlock!". Echter, niet alle deadlocks kunnen automatisch worden gedetecteerd.
Om deadlocks te voorkomen, is het belangrijk:
- Een consistente volgorde te hanteren bij het verkrijgen van mutexen.
- Te zorgen dat elke verzending naar een niet-buffered kanaal een bijbehorende leesactie heeft, en vice versa.
selectte gebruiken metdefaultof timeouts bij het werken met kanalen indien nodig.- De levensduur van goroutines en het sluiten van kanalen zorgvuldig te beheren.