Sobes.tech
Middle+

Окуучу жана жазуучу маселеси жөнүндө эмне билесиз?

sobes.tech AI

AIден жооп

Окууучу жана жазуучу маселеси — бул көптөгөн чөйрөлөрдө жалпы маалыматтарга кирүүнү синхрондоштуруу боюнча классикалык тапшырма.

Маселенин мааниси:

  • Көптөгөн агымдар (окуучулар) бир мезгилде маалыматтарды окушат.
  • Көптөгөн агымдар (жазуучулар) бир мезгилде маалыматтарды өзгөртүшөт.

Талаптар:

  • Окуучулар чектөөсүз бир мезгилде окуй алышат.
  • Жазуучулар маалыматтарга эксклюзивдүү кирүүгө ээ (жазуучу иштеп жатканда, башка эч ким — окуучу, жазуучу — кире албайт).
  • Бир мезгилде гана бир жазуучу иштей алат.
  • Эгер жазуучу күтүп жатса, жаңы окуучулар анын иши аяктагандан кийин гана кире алышы керек. Бул эреже "кайнатуу" маселесин алдын алат.

iOS үчүн чечимдер:

  • 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("Маалыматтарды жазуу...")
        }
    }
    
  • Конкуренттик Dispatch Queue менен Barrier (GCD): Көпчүлүк учурларда эң жакшы чечим. Конкуренттик катар колдонуп, окуу операцияларын параллелдүү аткарат. Жазуу операцияларында .barrier флагы колдонулат. Бул флаг менен операция катарга кошулганда, ал бардык алдынкы операциялар аяктагандан кийин гана ишке ашат, жана анын иштөө учурунда башка операциялар (окуу, жазуу) аткарылбайт. Барьердик операция аяктагандан кийин катар кайра конкуреттик болот. Ошентип, окуу параллелдүү, жазуу — эксклюзивдүү.

    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 флагы менен конкуреттик Dispatch Queue эң жакшы жана сунушталуучу ыкма болуп саналат.