Sobes.tech
Middle+

iOS-də deadlock-un ən parlaq nümunəsini göstərə bilərsinizmi?

sobes.tech Süni İntellekt

AI-dan cavab

iOS-də deadlock-in ən aydın nümunəsi, xüsusi mexanizmlərdən istifadə etmədən fon axınından UI-ni yeniləməyə cəhd edərkən baş verir.

// Bu kod deadlock və ya çöküşə səbəb olacaq (iOS versiyasına və kontekstə görə)
// əsas axın olmayan bir axından çağırıldıqda
DispatchQueue.global().async {
    // Arxa plan işini yerinə yetiririk...
    print("Arxa plan işi davam edir")

    // UI-ni birbaşa fon axınından yeniləməyə çalışırıq
    // Bu, istisna və ya deadlocka səbəb olacaq, çünki UIKit çox ipli deyil
    DispatchQueue.main.syncが必要です!
    // Bu, problemi göstərmək üçün əlavə olunub, real kodda belə etmək olmaz!
    DispatchQueue.main.sync {
        // Əsas axında bir etiketin yenilənməsi cəhdidir
        // Amma artıq əsas axinə sinxron gözləyirik, o, bloklanıb
        // özümüzün sinxron göndərmə blokumuz tərəfindən, deadlock yaranır.
        print("UI-ni yeniləməyə cəhd")
        // someLabel.text = "Arxa plandan yeniləndi" // Problemi yaradan nümunə sətiri
    }
    print("Arxa plan işi tamamlandı")
}

İzah:

UIKit (iOS-də istifadəçi interfeysini qurmaq üçün framework) ipli-əlaqəsiz deyil. Bütün UI əməliyyatları yalnız əsas axında həyata keçirilməlidir.

Yuxarıdakı nümunədə, DispatchQueue.main.sync { ... } blokunu arxa plan axınından çağırırsınızsa:

  1. Arxa plan axını bloklanır və əsas axının ona göndərdiyi bloku icra etməsini gözləyir.
  2. Əsas axın məşğul ola bilər və ya, bu ssenaridə, arxa plan axınında başlamalı olan əməliyyatın tamamlanmasını gözləyir (bu nümunədə belə deyil, sinxron göndərmə əsas axına arxa plan axınından artıq problemli olur).
  3. sync halında, arxa plan axını, əsas axın göndərilən bloku icra etmədən tamamlana bilməz. Əgər əsas axın artıq bloklanıbsa (məsələn, arxa plan axınında bir əməliyyatın tamamlanmasını gözləyir və o da öz növbəsində əsas axını gözləyirsə və ya sadəcə məşğuldursa), döngüvi gözləmə yaranır, yəni deadlock.

Düzgün həll yolu:

UI-ni yeniləmək üçün asinxron göndərmədən istifadə edin.

// Düzgün həll: UI-ni asinxron şəkildə əsas axında yeniləyin
DispatchQueue.global().async {
    // Arxa plan işini yerinə yetiririk...
    print("Arxa plan işi davam edir")

    // UI yeniləməsini asinxron şəkildə əsas axına göndəririk
    DispatchQueue.main.async {
        print("UI əsas axında yenilənir")
        // someLabel.text = "Arxa plandan yeniləndi" // UI yeniləmələri üçün düzgün yer
    }
    print("Arxa plan işi tamamlandı")
}

Burada, arxa plan axını, blok göndərilərkən bloklanmır və həm arxa plan tapşırığı, həm də əsas axın müstəqil işləyə bilir və deadlock qarşısı alınır.