Šta je deadlock pri radu sa goroutine?
sobes.tech АИ
Одговор од АИ
Deadlock (zastojevanje) je situacija kada dve ili više gorutina blokiraju jedna drugu, čekajući jedna drugu, i nijedna od njih ne može da nastavi sa izvršavanjem. Najčešće se javlja pri radu sa mutexima ili kanalima.
Primeri deadlock-a:
-
Blokiranje mutexa u različitom redosledu:
// Primer deadlock-a sa mutexima var mu1 sync.Mutex var mu2 sync.Mutex func goroutine1() { mu1.Lock() // Zauzima mu1 time.Sleep(100 * time.Millisecond) // Čeka malo mu2.Lock() // Pokušava da zauzme mu2 (koji drži goroutine2) fmt.Println("goroutine1 zauzela mu2") mu2.Unlock() mu1.Unlock() } func goroutine2() { mu2.Lock() // Zauzima mu2 time.Sleep(100 * time.Millisecond) // Čeka malo mu1.Lock() // Pokušava da zauzme mu1 (koji drži goroutine1) fmt.Println("goroutine2 zauzela mu1") mu1.Unlock() mu2.Unlock() }Goroutine1 je zauzela
mu1i čekamu2. Goroutine2 je zauzelamu2i čekamu1. Obje gorutine su blokirane. -
Slanje u nebuferisani kanal bez primaoca:
// Primer deadlock-a sa kanalom func main() { ch := make(chan int) //go func() { // Ako ne pokrenemo gorutinu za čitanje, doći će do deadlock-a // <-ch //}() ch <- 1 // Slanje u kanal bez aktivnog primaoca fmt.Println("Poslato u kanal") // Ova linija neće biti dostignuta }Slanje u nebuferisani kanal blokira dok druga gorutina ne počne da čita iz njega. Ako nema primaoca, javlja se deadlock.
-
Čitanje iz kanala bez pošiljaoca (nakon zatvaranja ili praznog bufferovanog):
// Primer deadlock-a pri čitanju iz kanala func main() { ch := make(chan int, 1) // Bufferovani kanal na 1 element ch <- 1 // Poslali smo 1 close(ch) // Zatvorili kanal <-ch // Pročitali 1 <-ch // Pokušavamo ponovo da čitamo iz zatvorenog i praznog kanala - deadlock }Čitanje iz zatvorenog, nepopunjenog kanala će biti uspešno. Čitanje iz zatvorenog i praznog ili iz otvorenog, ali praznog nebuferisanog kanala bez pošiljaoca dovodi do blokade.
Golang runtime može da otkrije određene tipove deadlock-ova (na primer, kada sve blokirane gorutine čekaju na primanje ili slanje od strane jedne gorutine), i u takvom slučaju program će neočekivano prekinuti sa porukom "fatal error: all goroutines are asleep - deadlock!". Međutim, nisu svi deadlock-ovi automatski detektovani.
Za sprečavanje deadlock-ova važno je:
- Poštovati konzistentan redosled zauzimanja mutexa.
- Osigurati da za svako slanje u nebuferisani kanal postoji odgovarajuće čitanje, i obrnuto.
- Pri radu sa kanalima koristiti
selectsadefaultgranom ili vremenskim ograničenjima po potrebi. - Pažljivo upravljati životnim ciklusom gorutina i zatvaranjem kanala.