Mis on deadlock, töötades goroutine'iga?
sobes.tech AI
Vastus AI-lt
Deadlock (sulg) — see olukord, kus kaks või rohkem gorutinit blokeerivad üksteist, oodates teineteist, ning ükski neist ei saa jätkata täitmist. Kõige sagedamini tekib see mutexide või kanalite kasutamisel.
Deadlocki näited:
-
Mutexide lukustamine erinevas järjekorras:
// Deadlocki näide mutexidega var mu1 sync.Mutex var mu2 sync.Mutex func goroutine1() { mu1.Lock() // Lukustab mu1 time.Sleep(100 * time.Millisecond) // Väike ooteaeg mu2.Lock() // Püüab lukustada mu2 (mida hoiab goroutine2) fmt.Println("goroutine1 saavutas mu2") mu2.Unlock() mu1.Unlock() } func goroutine2() { mu2.Lock() // Lukustab mu2 time.Sleep(100 * time.Millisecond) // Väike ooteaeg mu1.Lock() // Püüab lukustada mu1 (mida hoiab goroutine1) fmt.Println("goroutine2 saavutas mu1") mu1.Unlock() mu2.Unlock() }Goroutine1 saavutas
mu1ja ootabmu2. Goroutine2 saavutasmu2ja ootabmu1. Mõlemad gorutined on blokeeritud. -
Saatmine mittebuferiseeritud kanalile ilma vastuvõtja without:
// Deadlocki näide kanali kasutamisel func main() { ch := make(chan int) //go func() { // Kui me ei käivita lugemis-gorutinit, tekib deadlock // <-ch //}() ch <- 1 // Saatmine kanalile ilma aktiivse vastuvõtjata fmt.Println("Saadetud kanalile") // See rida ei jõua täide }Saatmine mittebuferiseeritud kanalile blokeerib kuni teine gorutina hakkab sellest lugema. Kui vastuvõtjat pole, tekib deadlock.
-
Lugemine kanalilt ilma saatjata (pärast sulgemist või tühja bufferit):
// Deadlocki näide kanali lugemisel func main() { ch := make(chan int, 1) // Bufferiga kanal 1 elemendiga ch <- 1 // Saatsime 1 close(ch) // Sulgesime kanali <-ch // Lugesime 1 <-ch // Püüame uuesti lugeda suletud ja tühjast kanalist - deadlock }Lugemine suletud, tühjast või avatud, kuid tühjast mittebuferiseeritud kanalist ilma saatjata põhjustab blokeeringu.
Golangi jooksukeskkond suudab tuvastada teatud deadlock-tüüpe (näiteks, kui kõik blokeeritud gorutined ootavad ühe gorutina vastuvõtu või saatmise lõpetamist), ning sellisel juhul lõpetab programm ootamatult sõnumiga "fatal error: all goroutines are asleep - deadlock!". Kuid mitte kõik deadlockid ei pruugi automaatselt tuvastada.
Deadlockide ennetamiseks on oluline:
- Säilitada järjepidev mutexide lukustamise järjekord.
- Tagada, et iga mittebuferiseeritud saatmisele vastab sobiv lugemine, ja vastupidi.
- Kanalitega töötades kasutada
selectkoosdefaultharuga või ajapiiranguid vastavalt vajadusele. - Hoolikalt hallata gorutinate elutsüklit ja kanalite sulgemist.