Mi az a deadlock a goroutine használata közben?
sobes.tech MI
Válasz az MI-től
Deadlock (akadály) — olyan helyzet, amikor két vagy több gorutina blokkol egymás várásában, és egyik sem tud továbbhaladni. Leggyakrabban mutexek vagy csatornák használata közben fordul elő.
Deadlock példák:
-
Mutexek blokkolása különböző sorrendben:
// Deadlock példa mutexekkel var mu1 sync.Mutex var mu2 sync.Mutex func goroutine1() { mu1.Lock() // megszerzi mu1-et time.Sleep(100 * time.Millisecond) // vár egy kicsit mu2.Lock() // megpróbálja megszerezni mu2-t (amelyet goroutine2 tart) fmt.Println("goroutine1 megszerezte mu2-t") mu2.Unlock() mu1.Unlock() } func goroutine2() { mu2.Lock() // megszerzi mu2-t time.Sleep(100 * time.Millisecond) // vár egy kicsit mu1.Lock() // megpróbálja megszerezni mu1-et (amelyet goroutine1 tart) fmt.Println("goroutine2 megszerezte mu1-et") mu1.Unlock() mu2.Unlock() }Goroutine1 megszerezte a
mu1-et és vár amu2-re. Goroutine2 megszerezte amu2-t és vár amu1-re. Mindkét gorutina blokkolva van. -
Üzenet küldése nem pufferelt csatornára anélkül, hogy fogadó lenne:
// Deadlock példa csatornával func main() { ch := make(chan int) //go func() { // Ha nem indítunk olvasó gorutint, deadlock lesz // <-ch //}() ch <- 1 // Küldés a csatornára anélkül, hogy fogadó lenne fmt.Println("Küldve a csatornára") // Ez a sor nem fog elérni }A nem pufferelt csatornára való küldés blokkol, amíg másik gorutina nem kezd olvasni róla. Ha nincs olvasó, deadlock történik.
-
Olvasás csatornáról fogadó nélkül (zárás vagy üres pufferelt csatorna után):
// Deadlock példa csatornáról olvasáskor func main() { ch := make(chan int, 1) // Pufferelt csatorna 1 elemmel ch <- 1 // Küldött egyet close(ch) // Bezárta a csatornát <-ch // Olvasott egyet <-ch // Újra próbál olvasni a zárt és üres csatornáról - deadlock }A zárt, nem üres csatornáról való olvasás sikeres lesz. A zárt és üres, vagy nyitott, de üres nem pufferelt csatornáról való olvasás blokkolást eredményez.
A Golang futási környezet képes bizonyos deadlock típusokat felismerni (például amikor minden blokkolt gorutina vár egyetlen gorutina fogadására vagy küldésére), és ilyen esetben a program váratlanul leáll a "fatal error: all goroutines are asleep - deadlock!" üzenettel. Azonban nem minden deadlock automatikusan észlelhető.
A deadlockok megelőzése érdekében fontos:
- Következetes mutex fogási sorrend betartása.
- Biztosítani, hogy minden nem pufferelt csatornába küldéshez tartozik megfelelő olvasás, és fordítva.
- Csatornákkal való munka során
select-et használnidefaultággal vagy időkorlátokat alkalmazni szükség szerint. - Gondosan kezelni a gorutinok életciklusát és a csatornák bezárását.