Sobes.tech
Middle+

Oxucu və yazıçı problemi haqqında nə bilirsiniz?

sobes.tech Süni İntellekt

AI-dan cavab

Oxucu və yazar problemi, çoxnüvəli mühitdə ümumi verilənlərə girişin sinxronizasiyası üçün klassik bir tapşırıqdır.

Problem:

  • Bir çox axın (oxucular) eyni zamanda məlumatları oxuyur.
  • Bir çox axın (yazıçılar) eyni zamanda məlumatları dəyişir.

Tələblər:

  • Oxucular məhdudiyyətsiz şəkildə eyni zamanda oxuya bilər.
  • Yazarlar məlumatlara eksklüziv girişə malikdir (yazar işləyərkən, heç kim – oxucu və ya yazar – giriş əldə edə bilməz).
  • Eyni zamanda yalnız bir yazar işləyə bilər.
  • Əgər yazar giriş gözləyirsə, yeni oxucular onun işini bitməyincə giriş əldə etməməlidir. Bu qayda "yazıçı aclığını" qarşısını alır.

iOS-də həllər:

  • NSLock: Ən sadə mexanizm, amma bu tapşırıq üçün optimal deyil, çünki həm oxumağı, həm də yazmağı bloklayır.

  • NSRecursiveLock: Eyni axın bir neçə dəfə bloklama əldə edə bilər. Tətbiq edilmir.

  • NSCondition: Daha çevik mexanizm, axınların müəyyən şərtlərin yerinə yetirilməsini gözləməsinə imkan verir. Oxucu/yazıcı loqikasını həyata keçirmək üçün istifadə oluna bilər, amma əl ilə bloklama və şərtlərin idarə olunmasını tələb edir.

  • Serial Dispatch Queue (GCD): Bütün oxuma və yazma əməliyyatları üçün ardıcıl növbənin yaradılması. Yazma əməliyyatları sinxron, oxuma isə asinxron həyata keçirilə bilər, amma əvvəlki əməliyyatlar tamamlandıqdan sonra. Bu sadə həll olsa da, oxuma üçün optimal deyil, çünki oxuma paralel şəkildə həyata keçirilə bilməz.

    let readWriteQueue = DispatchQueue(label: "com.example.readwrite", attributes: .concurrent)
    
    func readData() {
        readWriteQueue.async {
            // Məlumatların oxunması loqikası
            print("Məlumatlar oxunur...")
        }
    }
    
    func writeData() {
        readWriteQueue.sync(flags: .barrier) {
            // Məlumatların yazılması loqikası
            print("Məlumatlar yazılır...")
        }
    }
    
  • Concurrent Dispatch Queue with Barrier (GCD): Əksər hallarda optimal həll. Konkurrent növbə istifadə edilərək oxuma əməliyyatları paralel şəkildə həyata keçirilir. Yazma əməliyyatları üçün .barrier bayrağı istifadə olunur. .barrier bayrağı ilə növbəyə əlavə olunan əməliyyat, əvvəlki bütün əməliyyatların tamamlanmasını gözləyir, sonra icra olunur və onun icrası zamanı digər əməliyyatlar (oxuma və ya yazma) həyata keçirilmir. Barrierdən sonra növbə yenidən konkurrent olur. Beləliklə, oxuma paralel, yazma isə eksklüzivdir.

    let readWriteQueue = DispatchQueue(label: "com.example.readwrite", attributes: .concurrent)
    
    func readData() {
        readWriteQueue.async {
            // Məlumatların oxunması loqikası
            print("Məlumatlar oxunur...")
        }
    }
    
    func writeData() {
        readWriteQueue.sync(flags: .barrier) {
            // Məlumatların yazılması loqikası
            print("Məlumatlar yazılır...")
        }
    }
    

    Bu, serial növbə üçün olan kodla eynidir, amma .concurrent atributu növbəni konkurrent edir. .barrier bayrağı isə növbənin bu əməliyyat üçün ardıcıl davranmasını təmin edir.

  • os_unfair_lock (iOS 10+): Aşağı səviyyəli bloklama, NSLock-dən daha məhsuldardır. Əgər maksimum performans və ya xüsusi davranış tələb olunursa, oxucu-yazıcı loqikasını əl ilə həyata keçirmək üçün istifadə oluna bilər. Diqqətli istifadə tələb edir.

Həll seçimi, tətbiqin konkret tələblərinə, oxuma və yazma əməliyyatlarının tezliyinə və lazım olan performans səviyyəsinə bağlıdır. Əksər hallarda, .barrier bayrağı ilə konkurrent dispatch queue istifadə etmək ən balanslı və tövsiyə olunan yanaşmadır.