Sobes.tech
Middle+

Ինչ եք գիտակցում ընթերցողի և գրողի խնդիրների մասին?

sobes.tech AI

Պատասխան AI-ից

Կարդացողի և գրողի խնդիրն ավանդական խնդիր է համատեղ տվյալների մուտքի սինխրոնիզացման համար բազմատան միջավայրում:

Համակարգի էությունը՝

  • Շատ թելեր (կարդացողներ) միաժամանակ ընթերցում են տվյալները:
  • Շատ թելեր (գրողներ) միաժամանակ փոփոխում են տվյալները:

Անհրաժեշտություններ՝

  • Կարդացողները կարող են ընթերցել միաժամանակ առանց սահմանափակումների:
  • Գրողները ունեն բացառիկ մուտք տվյալների (մինչև որ գրողը աշխատում է, ոչ ոք — ոչ կարդացող, ոչ գրող — չի կարող մուտք ունենալ):
  • Միաժամանակ կարող է աշխատել միայն մեկ գրող:
  • Եթե գրողը սպասում է մուտքի, նոր կարդացողները չպետք է ստանան մուտք մինչև գրողը ավարտի իր աշխատանքը: Այս կանոնը կանխում է "գլատչություն" գրողների համար:

ԻOS-ում լուծումներ՝

  • NSLock՝ ամենահեշտ մեխանիզմը, բայց ոչ օպտիմալ այս խնդրի համար, քանի որ արգելափակում է ինչպես ընթերցումը, այնպես էլ գրությունը:

  • NSRecursiveLock՝ թույլ է տալիս նույն թելին մի քանի անգամ ստանալ արգելափակումը:

  • NSCondition՝ ավելի ճկուն մեխանիզմ, թույլ է տալիս թելերին սպասել որոշ պայմանների կատարմանը:

  • Serial Dispatch Queue (GCD)՝ ստեղծել մի շարք, որը կկատարի բոլոր ընթերցումների և գրումների օպերացիաները:

    let readWriteQueue = DispatchQueue(label: "com.example.readwrite", attributes: .concurrent)
    
    func readData() {
        readWriteQueue.async {
            // Տվյալների ընթերցման լոգիկա
            print("Տվյալների ընթերցում...")
        }
    }
    
    func writeData() {
        readWriteQueue.sync(flags: .barrier) {
            // Տվյալների գրելու լոգիկա
            print("Տվյալների գրառում...")
        }
    }
    
  • Concurrent Dispatch Queue with Barrier (GCD)՝ լավագույն լուծում է մեծ մասի դեպքերում:

    let readWriteQueue = DispatchQueue(label: "com.example.readwrite", attributes: .concurrent)
    
    func readData() {
        readWriteQueue.async {
            // Տվյալների ընթերցման լոգիկա
            print("Տվյալների ընթերցում...")
        }
    }
    
    func writeData() {
        readWriteQueue.sync(flags: .barrier) {
            // Տվյալների գրելու լոգիկա
            print("Տվյալների գրառում...")
        }
    }
    

Այս կոդը նույնն է, ինչ սերիական հերթի դեպքում, բայց .concurrent հատկությունը դարձնում է հերթը մրցակցային:

.barrier նշանը ստիպում է հերթին վարել որպես սերիական միայն այս հատուկ օպերացիայի համար:

  • os_unfair_lock (iOS 10+)՝ ցածր մակարդակի արգելափակիչ, ավելի արդյունավետ, քան NSLock:

Ընտրությունը կախված է կոնկրետ պահանջներից, ընթերցման և գրության հաճախությունից, և անհրաժեշտ կատարողականի մակարդակից:

Ամեն դեպքում, մրցակցային հերթի օգտագործումը .barrier նշանով ամենաբალանսավորված և խորհուրդ է տրվում iOS-ում։