Goroutine ilə işləyərkən deadlock nədir?
sobes.tech Süni İntellekt
AI-dan cavab
Deadlock (ölü nöqtə) — iki və ya daha çox goroutine-in bir-birini gözləyərək bloklandığı vəziyyətdir və heç biri icra etməyə davam edə bilmir. Bu, ən çox mutexlər və ya kanallar ilə işləyərkən baş verir.
Deadlock nümunələri:
-
Mutexlərin fərqli ardıcıllıqla bloklanması:
// Mutexlərlə deadlock nümunəsi var mu1 sync.Mutex var mu2 sync.Mutex func goroutine1() { mu1.Lock() // mu1-i bloklayır time.Sleep(100 * time.Millisecond) // Bir az gözləyir mu2.Lock() // mu2-ni bloklamağa çalışır (goroutine2 tərəfindən tutulur) fmt.Println("goroutine1 mu2-ni əldə etdi") mu2.Unlock() mu1.Unlock() } func goroutine2() { mu2.Lock() // mu2-ni bloklayır time.Sleep(100 * time.Millisecond) // Bir az gözləyir mu1.Lock() // mu1-i bloklamağa çalışır (goroutine1 tərəfindən tutulur) fmt.Println("goroutine2 mu1-i əldə etdi") mu1.Unlock() mu2.Unlock() }Goroutine1 mu1-i blokladı və mu2-ni gözləyir. Goroutine2 mu2-ni blokladı və mu1-i gözləyir. Hər ikisi bloklanıb.
-
Buffersiz kanalə göndəriş və qəbul edən olmadan:
// Deadlock nümunəsi kanal ilə func main() { ch := make(chan int) //go func() { // Əgər oxumaq üçün goroutine başlamazsa, deadlock yaranar // <-ch //}() ch <- 1 // Kanalə göndəriş, qəbul edən olmadan fmt.Println("Kanalə göndərildi") // Bu sətir çatmayacaq }Buffersiz kanala göndəriş, başqa bir goroutine oxumağa başlayana qədər bloklanır. Əgər qəbul edən yoxdursa, deadlock yaranır.
-
Kanaldan qəbul, göndərən olmadan (bağlandıqdan və ya boş buffer ilə):
// Kanalın bağlanması və boş buffer ilə oxumaqda deadlock nümunəsi func main() { ch := make(chan int, 1) // 1 elementli bufferli kanal ch <- 1 // Göndərildi close(ch) // Kanal bağlandı <-ch // 1 oxundu <-ch // Yenidən bağlanmış və boş kanaldan oxumağa cəhd - deadlock }Bağlanmış və boş olmayan kanaldan oxuma uğurlu olacaq. Bağlanmış və boş kanal və ya açıq, lakin boş kanal, göndərən olmadan bloklanmaya səbəb olur.
Golang-in çalışma vaxtı bəzi deadlock tiplərini aşkar edə bilər (məsələn, bütün bloklanmış goroutine-lər tək bir goroutine-dən alma və ya göndərmə gözləyirsə), və bu halda proqram "fatal error: all goroutines are asleep - deadlock!" mesajı ilə ani şəkildə dayanacaq. Ancaq, bütün deadlock-lər avtomatik olaraq aşkar edilə bilməz.
Deadlock-ları qarşısını almaq üçün:
- Mutexlərin tutma ardıcıllığını davamlı saxlayın.
- Hər bir buffersiz kanala göndərmə üçün uyğun bir qəbul olduğunu təmin edin və əksinə.
- Lazım gələrsə,
selectvədefaultvə ya zaman aşımı ilə kanallarla işləyin. - Goroutine-lərin həyat dövrünü və kanalların bağlanmasını diqqətlə idarə edin.