O'quvchilar - yozuvchilar muammosi - Readers–writers problem

Yilda Kompyuter fanlari, o'quvchi-yozuvchilar muammolari da keng tarqalgan hisoblash muammosiga misollar bir vaqtda. Muammolarning kamida uchta o'zgarishi mavjud, ular ko'pchilik bir-biriga mos keladigan vaziyatlarni hal qiladi iplar bir vaqtning o'zida bir xil umumiy resursga kirishga harakat qiling.

Ba'zi bir mavzular o'qishi yoki yozishi mumkin, chunki cheklash bilan biron bir mavzu o'qish yoki yozish uchun umumiy manbaga kirish huquqiga ega emas, boshqasi esa unga yozish paytida. (Xususan, biz bir nechta mavzularni bir vaqtning o'zida umumiy resursni o'zgartirishiga to'sqinlik qilmoqchimiz va bir vaqtning o'zida ikki yoki undan ortiq o'quvchiga umumiy resursga kirish imkoniyatini beramiz). A o'quvchilar - yozuvchi qulf a ma'lumotlar tuzilishi bu bir yoki bir nechta o'quvchi-yozuvchining muammolarini hal qiladi.

O'quvchi-yozuvchilarning asosiy muammosi birinchi bo'lib Kurtua tomonidan ishlab chiqilgan va hal qilingan va boshq.[1][2]

Birinchi o'quvchi-yozuvchilar muammosi

Yuqorida keltirilgan asosiy cheklovlarga ega bo'lgan umumiy xotira maydoni (muhim bo'lim) mavjud deylik. O'zaro chiqarib yuborish ortida umumiy ma'lumotlarni himoya qilish mumkin muteks, bu holda bir vaqtning o'zida ikkita oqim ma'lumotlarga kira olmaydi. Biroq, bu echim sub-optimaldir, chunki o'quvchi bo'lishi mumkin R1 qulfga, keyin esa boshqa o'quvchiga ega bo'lishi mumkin R2 kirishni so'raydi. Bu aqlsiz bo'lar edi R2 qadar kutish R1 o'z o'qish operatsiyasini boshlashdan oldin amalga oshirildi; o'rniga, R2 bilan birga manbani o'qishga ruxsat berish kerak R1 chunki o'qish ma'lumotni o'zgartirmaydi, shuning uchun bir vaqtning o'zida o'qish xavfsizdir. Bu motivatsiya birinchi o'quvchi-yozuvchilar muammosi, unda cheklov qo'shiladi agar ulush hozirda o'qish uchun ochilgan bo'lsa, hech bir o'quvchi kutib turilmaydi. Bu ham deyiladi o'quvchilarning afzalligi, uning echimi bilan:

 1 semafora manba=1; 2 semafora rmutex=1; 3 qayta hisoblash=0; 4  5 /* 6    resource.P () kutishga teng (resurs) 7    resource.V () signal (resurs) ga teng 8    rmutex.P () kutishga teng (rmutex) 9    rmutex.V () signalga teng (rmutex)10 */11 12 yozuvchi() {13     manba.P();          // Umumiy faylni yozuvchi uchun bloklang14 15     <TANQID Bo'lim>16     // Yozish tugadi17 18     <CHIQISH Bo'lim>19     manba.V();          // Umumiy faylni boshqa o'quvchilar uchun ishlatish uchun qo'yib yuboring. Yozuvchilarga buni talab qiladigan o'quvchilar bo'lmasa ruxsat beriladi.20 }21 22 o'quvchi() {23     rmutex.P();           // Siz u erda bo'lganingizda boshqa biron bir o'quvchi  bo'limini bajara olmasligiga ishonch hosil qiling24     <TANQID Bo'lim>25     qayta hisoblash++;          // Muhim bo'limga kirishga harakat qilayotgan o'quvchi ekanligingizni ko'rsating26     agar (qayta hisoblash == 1)   // CS-ga kirishga harakat qilayotgan birinchi o'quvchi ekanligingizni tekshiradi27         manba.P();     // Agar siz birinchi o'quvchi bo'lsangiz, manbani yozuvchilardan bloklang. Resurs keyingi o'quvchilar uchun saqlanib qoladi28     <CHIQISH TANQID Bo'lim>29     rmutex.V();           // ozod qilish30 31     // O'qishni bajaring32 33     rmutex.P();           // Siz bo'lganingizda boshqa biron bir o'quvchi  bo'limini bajara olmasligiga ishonch hosil qiling34     <TANQID Bo'lim>35     qayta hisoblash--;          // Umumiy manbaga ehtiyoj sezmayotganingizni ko'rsating. Kamroq o'quvchi36     agar (qayta hisoblash == 0)   // Birgalikda faylni o'qiyotgan oxirgi (faqat) o'quvchi ekanligingizni tekshiring37         manba.V();     // Agar siz oxirgi o'quvchi bo'lsangiz, unda siz resursni ochishingiz mumkin. Bu yozuvchilar uchun mavjud.38     <CHIQISH TANQID Bo'lim>39     rmutex.V();           // ozod qilish40 }

O'quvchilar / yozuvchilar muammosining ushbu echimida, agar mavjud bo'lsa, birinchi o'quvchi resursni (umumiy faylni) bloklashi kerak. Fayl yozuvchilardan qulflangandan so'ng, uni ko'plab keyingi o'quvchilar qayta qulflash uchun foydalanmasdan foydalanishlari mumkin.

Ga kirishdan oldin muhim bo'lim, har bir yangi o'quvchi kirish qismidan o'tishi kerak. Biroq, kirish qismida bir vaqtning o'zida faqat bitta o'quvchi bo'lishi mumkin. Bu oldini olish uchun qilingan poyga shartlari o'quvchilarga (shu nuqtai nazardan, poyga sharti - bu ikki yoki undan ortiq ipning bir vaqtning o'zida uyg'onishi va tanqidiy bo'limga kirishga urinish holati; qo'shimcha cheklovlarsiz xatti-harakatlar noaniq bo'ladi. Masalan, ikkita o'quvchi o'qish sonini bir xilda oshiradi vaqt, va ikkalasi ham resursni blokirovka qilishga urinib, bitta o'quvchining bloklanishiga olib keladi). Buni amalga oshirish uchun kirgan har bir o'quvchi u bilan tugamaguncha o'zlari uchun qulflab qo'yadi. Ayni paytda o'quvchilar resursni qulflamaydilar. Ular faqat kirish qismini blokirovka qilishmoqda, shunda ular ichida boshqa o'quvchi uni kirita olmaydi. O'quvchi kirish qismini bajarib bo'lgandan so'ng, uni muteksga signal berish orqali ochadi. Yuqoridagi kodda unga signal berish mutex.V () ga teng. Xuddi shu narsa uchun amal qiladi. Bir vaqtning o'zida chiqish bo'limida bitta o'quvchi bo'lishi mumkin emas, shuning uchun har bir o'quvchi uni ishlatishdan oldin Chiqish qismini o'zlari uchun talab qilishi va qulflashi kerak.

Birinchi o'quvchi kirish qismida bo'lganidan so'ng, u resursni bloklaydi. Buni amalga oshirish har qanday yozuvchining unga kirishiga yo'l qo'ymaydi. Keyingi o'quvchilar faqat bloklangan (yozuvchilardan) manbadan foydalanishlari mumkin. Oxirini tugatish uchun o'quvchi (readcount o'zgaruvchisi tomonidan ko'rsatilgan) manbani qulfdan chiqarishi va shu bilan uni yozuvchilarga taqdim etishi kerak.

Ushbu echimda har bir yozuvchi manbani alohida talab qilishi kerak. Bu shuni anglatadiki, o'quvchilar oqimi keyinchalik barcha potentsial yozuvchilarni yopib qo'yishi va ularni och qoldirishi mumkin. Bu shunday, chunki birinchi o'quvchi resursni qulflagandan so'ng, hech bir yozuvchi uni chiqmasdan turib bloklay olmaydi. Va u faqat oxirgi o'quvchi tomonidan chiqariladi. Demak, ushbu echim adolatni qondirmaydi.

Ikkinchi o'quvchi-yozuvchilar muammosi

Birinchi yechim suboptimal, chunki o'quvchi bo'lishi mumkin R1 qulf bo'lishi mumkin, yozuvchi V qulfni kuting va keyin o'quvchi R2 kirishni so'raydi. Bu adolatsiz bo'lar edi R2 oldinda, zudlik bilan sakrash V; agar bu tez-tez sodir bo'lsa, V bo'lardi ochlik. Buning o'rniga, V imkon qadar tezroq boshlash kerak. Bu motivatsiya ikkinchi o'quvchi-yozuvchilar muammosi, unda cheklov qo'shiladi navbatga qo'shilgandan keyin biron bir yozuvchi o'ta zarur vaqtdan ko'proq kutib turilmasligi kerak. Bu ham deyiladi yozuvchilarning afzalligi.

Yozuvchilarning afzal stsenariysi uchun echim:[1]

 1 int qayta hisoblash, yozuvlar ro'yxati;                   // (boshlang'ich qiymati = 0) 2 semafora rmutex, wmutex, o'qing, manba; // (boshlang'ich qiymati = 1) 3  4 // O'QUVCHI 5 o'quvchi() { 6 <KIRISH Bo'lim> 7   o'qing.P();                 // O'quvchi kirishga harakat qilayotganini ko'rsating 8   rmutex.P();                  // boshqa o'quvchilar bilan poyga holatidan qochish uchun kirish qismini qulflang 9   qayta hisoblash++;                 // o'zingizni o'quvchi sifatida hisobot qiling10   agar (qayta hisoblash == 1)          // birinchi o'quvchi ekanligingizni tekshiradi11     manba.P();              // agar siz birinchi o'quvchi bo'lsangiz, manbani qulflang12   rmutex.V();                  // boshqa o'quvchilar uchun kirish qismi13   o'qing.V();                 // manbaga kirishga urinish tugaganligini bildiring14 15 <TANQID Bo'lim>16 // o'qish amalga oshiriladi17 18 <CHIQISH Bo'lim>19   rmutex.P();                  // zaxiradan chiqish bo'limi - o'quvchilar bilan poyga holatidan qochadi20   qayta hisoblash--;                 // ketayotganingizni bildiring21   agar (qayta hisoblash == 0)          // oxirgi o'quvchi ketayotganingizni tekshiradi22     manba.V();              // agar oxirgi bo'lsa, siz bloklangan manbani bo'shatishingiz kerak23   rmutex.V();                  // boshqa o'quvchilar uchun chiqish qismi24 }25 26 // YOZUVCHI27 yozuvchi() {28 <KIRISH Bo'lim>29   wmutex.P();                  // yozuvchilar uchun zaxira kirish bo'limi - poyga sharoitlaridan qochadi30   yozuvlar ro'yxati++;                // o'zingizni yozuvchi sifatida xabar bering31   agar (yozuvlar ro'yxati == 1)         // siz birinchi yozuvchi ekanligingizni tekshiradi32     o'qing.P();               // agar siz birinchi bo'lsangiz, unda o'quvchilarni blokirovka qilishingiz kerak. Ularning CS-ga kirishiga yo'l qo'ymaslik33   wmutex.V();                  // kirish qismi34   manba.P();                // o'zingiz uchun resursni zaxiralash - boshqa mualliflarning bir vaqtning o'zida umumiy resursni tahrirlashiga yo'l qo'ymaydi35 <TANQID Bo'lim>36   // yozish amalga oshiriladi37   manba.V();                // faylni chiqarish38 39 <CHIQISH Bo'lim>40   wmutex.P();                  // zaxira chiqish qismi41   yozuvlar ro'yxati--;                // ketayotganingizni bildiring42   agar (yozuvlar ro'yxati == 0)         // oxirgi yozuvchi ekanligingizni tekshiradi43     o'qing.V();               // oxirgi yozuvchi bo'lsangiz, o'quvchilarning qulfini ochishingiz kerak. O'qish uchun CS-ga kirishga harakat qilishlariga imkon beradi44   wmutex.V();                  // chiqish qismi45 }

Ushbu yechimda yozuvchilarga ustunlik beriladi. Bu har bir o'quvchini readtry semaforini alohida qulflash va ozod qilishga majbur qilish orqali amalga oshiriladi. Boshqa tomondan, yozuvchilar uni birma-bir qulflashlari shart emas. Faqat birinchi yozuvchi o'qish rejimini bloklaydi va undan keyin keyingi barcha yozuvchilar avvalgi yozuvchi tomonidan bo'shatilganidek, shunchaki manbadan foydalanishi mumkin. Oxirgi yozuvchi readtry semaforini qo'yib yuborishi kerak, shu bilan o'quvchilar o'qishga harakat qilishlari uchun eshik ochiladi.

Agar o'qish semasi avval yozuvchi tomonidan o'rnatilgan bo'lsa, hech bir o'quvchi kirish qismiga kira olmaydi. O'quvchi so'nggi yozuvchini manba va o'qish semaforlarini ochishini kutishi kerak. Boshqa tomondan, agar ma'lum bir o'quvchi o'qish semaforini qulflagan bo'lsa, bu har qanday potentsial bir vaqtda yozuvchiga kirish qismida o'quvchi borligini ko'rsatadi. Shunday qilib, yozuvchi o'quvchining o'qishni boshlashini kutadi va yozuvchi uni darhol o'zi va keyingi barcha yozuvchilar uchun qulflaydi. Biroq, yozuvchi hozirgi o'quvchi manbani chiqarmaguncha, resursga kira olmaydi, bu faqat o'quvchi tanqidiy qismdagi resurs bilan tugagandan so'ng sodir bo'ladi.

Resurs semaforini yozuvchi ham, o'quvchi ham kirish qismida qulflashi mumkin. Ular buni faqat o'qish semaforini birinchi marta qulflagandan so'ng qilishlari mumkin, buni bir vaqtning o'zida ulardan biri amalga oshirishi mumkin.

Agar o'quvchiga readtry semaforining holati ko'rsatilgandek, manbaga kirishni xohlaydigan yozuvchilar bo'lmasa, u holda o'quvchilar manbani qulflamaydilar. Bu amaldagi o'quvchi o'qishni tugatishi bilan yozuvchiga zudlik bilan manbani boshqarish huquqini berish uchun amalga oshiriladi. Aks holda, yozuvchi readtry semaforini ochishdan oldin o'quvchilarning navbatini kutishini kutishi kerak edi. Yozuvchi paydo bo'lishi bilanoq, u o'qishni o'rnatishga harakat qiladi va hozirgi o'quvchining o'qishni kutishini kutib, u erda osib qo'yadi. Keyinchalik, o'quvchi o'qishni tugatishi bilanoq, resursni nazorat qiladi va kelajakdagi barcha o'quvchilarni blokirovka qiladi. Keyingi barcha kitobxonlar yozuvchilarni manba bilan tugashini va readtryni chiqarib darvozani ochishini kutib, o'qish semaforida to'xtashadi.

Rmutex va wmutex birinchi echimdagi kabi to'liq ishlatiladi. Ularning yagona maqsadi - o'quvchilar va yozuvchilar kirish yoki chiqish bo'limlarida bo'lganlarida poyga sharoitlaridan qochishdir.

Uchinchi o'quvchi-yozuvchilar muammosi

Darhaqiqat, ikkala muammoli bayonotda nazarda tutilgan echimlar ochlikka olib kelishi mumkin - birinchisi navbatda yozuvchilarni och qoldirishi mumkin, ikkinchisi esa o'quvchilarni och qoldirishi mumkin. Shuning uchun uchinchi o'quvchi-yozuvchilar muammosi ba'zan taklif qilinadi, bu esa cheklovni kuchaytiradi hech qanday ipning och qolishiga yo'l qo'yilmaydi; ya'ni umumiy ma'lumotlarga blokirovka qilish operatsiyasi har doim cheklangan vaqt ichida tugaydi va o'quvchilar uchun ham, yozuvchilar uchun ham adolatli echim quyidagicha bo'lishi mumkin:

 1 int qayta hisoblash;                // 0 ga init; hozirda manbadan foydalanayotgan o'quvchilar soni 2  3 // 1 ga boshlangan barcha semaforlar 4 semafora manba;           // resursga kirishni (o'qish / yozishni) boshqaradi 5 semafora rmutex;             // o'zgarishlarni umumiy hisob raqamiga sinxronlashtirish uchun 6 semafora xizmat navbati;       // FAIRNESS: so'rovlar tartibini saqlaydi (signal FIFO bo'lishi kerak) 7  8 // O'QUVCHI 9 o'quvchi() {10 <KIRISH Bo'lim>11   xizmat navbati.P();           // xizmat ko'rsatish uchun navbat kuting12   rmutex.P();                 // readcount-ga eksklyuziv kirishni so'rash13   qayta hisoblash++;                // faol o'quvchilar sonini yangilash14   agar (qayta hisoblash == 1)         // agar men birinchi o'quvchi bo'lsam15     manba.P();             // o'quvchilar uchun manbalarga kirishni so'rash (yozuvchilar bloklangan)16   xizmat navbati.V();           // keyingi qatorga xizmat ko'rsatilsin17   rmutex.V();                 // readcount-ga kirish uchun ruxsat18     19 <TANQID Bo'lim>20 // o'qish amalga oshiriladi21     22 <CHIQISH Bo'lim>23   rmutex.P();                 // readcount-ga eksklyuziv kirishni so'rash24   qayta hisoblash--;                // faol o'quvchilar sonini yangilash25   agar (qayta hisoblash == 0)         // agar o'quvchi qolmasa26     manba.V();             // hamma uchun resursdan foydalanishni bo'shatish27   rmutex.V();                 // readcount-ga kirish uchun ruxsat28 }29 30 // YOZUVCHI31 yozuvchi() {32 <KIRISH Bo'lim>33   xizmat navbati.P();           // xizmat ko'rsatish uchun navbat kuting34   manba.P();               // resursga eksklyuziv kirishni so'rash35   xizmat navbati.V();           // keyingi qatorga xizmat ko'rsatilsin36     37 <TANQID Bo'lim>38 // yozish amalga oshiriladi39     40 <CHIQISH Bo'lim>41   manba.V();               // keyingi o'quvchi / yozuvchi uchun manba ruxsatini chiqarish42 }

Ushbu echim faqat semaforlar iplarni blokirovka qilish va qo'yib yuborishda birinchi navbatda birinchi tartibni saqlab qolgandagina, "hech qanday ipning och qolishiga yo'l qo'ymaslik" shartini qondirishi mumkin. Aks holda, bloklangan yozuvchi, masalan, semaforni imkon qadar kamaytiradigan boshqa yozuvchilar tsikli bilan abadiy to'siq bo'lib qolishi mumkin.

Oddiy o'quvchi yozuvchisi muammosi

Faqat ikkita semafordan foydalanadigan va buferda ma'lumotlarni o'qish uchun bir qator o'quvchilarga ehtiyoj sezmaydigan eng oddiy o'quvchi yozuvchisi muammosi.

Iltimos, ushbu echim umumiy ishdan ko'ra osonroq bo'lishiga e'tibor bering, chunki u tenglashtirilgan Chegaralangan bufer muammo va shuning uchun faqat N O'quvchilarga parallel ravishda kirishga ruxsat beriladi, N buferning kattaligi.

O'quvchi

qil {    Kutmoq(o'qing)    ............    o'qish ma'lumotlar    ............    signal(yozmoq)} esa (Rost);

Yozuvchi

qil {    Kutmoq(yozmoq)    .............    yozish ma'lumotlar    .............    signal(o'qing)} esa (Rost);

Algoritm

  1. Reader semafor tufayli Reader-ning orqasidan yuguradi.
  2. Yozish semasi 0 ga yetganda yozuvchi yozishni to'xtatadi.
  3. O'qilgan semafor 0 ga etganida o'quvchi o'qishni to'xtatadi.

Yozuvchida semafor yozish qiymati semaforni o'qish uchun, o'quvchida esa o'qish qiymati tsikl tugashi bilan yozish uchun beriladi.

Shuningdek qarang

Adabiyotlar

  1. ^ a b Kurtua, P. J .; Heymans, F .; Parnas, D. L. (1971). "" O'quvchilar "va" Yozuvchilar bilan bir vaqtda nazorat"" (PDF). ACM aloqalari. doi:10.1145/362759.362813.
  2. ^ Taubenfeld, Gadi (2006). Sinxronizatsiya algoritmlari va bir vaqtda dasturlash. Pearson ta'limi. p. 301.
  • Morris JM (1979). O'zaro chiqarib tashlash muammosining ochliksiz echimi. Inf Process Lett 8: 76-80
  • O'quvchi-yozuvchiga adolatli echim - faqat semaforlar bilan bog'liq muammo. X. Ballhauzen, 2003 yil arXiv:cs / 0303005
  • Reader-Writer muammolari uchun tezkor adolatli echim. V. Popov, O. Mazonka 2013 yil arXiv:1309.4507

Tashqi havolalar