Goroutine bilan ishlashda deadlock nima?
sobes.tech AI
AIdan javob
Deadlock (o'lim) — bu holatda, ikki yoki undan ortiq gorutinalar bir-birini kutib, bloklanib qoladigan holat. Bu holat ko'proq mutexlar yoki kanallar bilan ishlashda yuzaga keladi.
Deadlock misollari:
-
Mutexlarni turli tartibda bloklash:
// Mutexlar bilan deadlock misoli var mu1 sync.Mutex var mu2 sync.Mutex func goroutine1() { mu1.Lock() // mu1 ni bloklaydi time.Sleep(100 * time.Millisecond) // Biroz kutadi mu2.Lock() // mu2 ni bloklamoqchi (goroutine2 tomonidan band) fmt.Println("goroutine1 mu2 ni egalladi") mu2.Unlock() mu1.Unlock() } func goroutine2() { mu2.Lock() // mu2 ni bloklaydi time.Sleep(100 * time.Millisecond) // Biroz kutadi mu1.Lock() // mu1 ni bloklamoqchi (goroutine1 tomonidan band) fmt.Println("goroutine2 mu1 ni egalladi") mu1.Unlock() mu2.Unlock() }Goroutine1
mu1ni blokladi vamu2ni kutmoqda. Goroutine2mu2ni blokladi vamu1ni kutmoqda. Ikkalasi ham bloklangan. -
Buffersiz kanalga yuborish, qabul qiluvchi bo'lmagan holda:
// Deadlock misoli kanal bilan func main() { ch := make(chan int) //go func() { // Agar o'qish uchun goroutine ishga tushirilmasa, deadlock yuzaga keladi // <-ch //}() ch <- 1 // Kanalga yuborish, qabul qiluvchi bo'lmasa fmt.Println("Yuborildi kanalga") // Bu satrga yetib borilmaydi }Buffersiz kanalga yuborish, boshqa goroutine o'qishni boshlaguncha bloklanadi. Agar qabul qiluvchi bo'lmasa, deadlock yuzaga keladi.
-
Kanaldan qabul qilish, yuboruvchi bo'lmagan holda (yopilgan yoki bo'sh buffer bilan):
// Kanal yopilgan va bo'sh bo'lsa, o'qish deadlockga olib keladi func main() { ch := make(chan int, 1) // 1 elementli bufferli kanal ch <- 1 // Yuborildi close(ch) // Kanal yopildi <-ch // 1 o'qildi <-ch // Yopilgan va bo'sh kanalni yana o'qishga urinish - deadlock }Yopilgan va bo'sh bo'lmagan kanaldan o'qish muvaffaqiyatli bo'ladi. Yopilgan va bo'sh kanal yoki ochiq, ammo bo'sh kanal, yuboruvchi bo'lmagan holda, blokirovkaga olib keladi.
Golang runtime ba'zi deadlock turlarini aniqlay oladi (masalan, barcha bloklangan gorutinalar yagona goroutine'dan qabul qilish yoki yuborishni kutayotgan bo'lsa), va bu holatda dastur "fatal error: all goroutines are asleep - deadlock!" xabari bilan to'xtaydi. Biroq, barcha deadlocklar avtomatik tarzda aniqlanmaydi.
Deadlocklarni oldini olish uchun:
- Mutexlarni tutishda ketma-ketlikni muvofiqlashtirish.
- Har bir buffersiz kanalda yuborish uchun mos o'qish mavjudligini ta'minlash va aksincha.
- Kerak bo'lsa,
selectvadefaultyoki timeoutlardan foydalanish. - Gorutinalarning hayot davrini va kanallarni ehtiyotkorlik bilan boshqarish.