ABA muammosi - ABA problem

Yilda ko'p tishli hisoblash, ABA muammosi sinxronizatsiya paytida, joylashuv ikki marta o'qilganda, ikkala o'qish uchun ham bir xil qiymatga ega bo'lganda va "hech narsa o'zgarmaganligini" ko'rsatishda "qiymat bir xil" ishlatiladi. Biroq, boshqa bir o'q ikki o'qish o'rtasida bajarilishi va qiymatni o'zgartirishi, boshqa ishni bajarishi, keyin qiymatni qaytarishi mumkin, shuning uchun birinchi ipni "hech narsa o'zgargani yo'q" deb aldaydi, garchi ikkinchi ip bu taxminni buzadigan ish qilgan bo'lsa ham.

ABA muammosi ko'p bo'lsa paydo bo'ladi iplar (yoki jarayonlar ) birgalikda ma'lumotlarga kirish. Quyida ABA muammosiga olib keladigan voqealar ketma-ketligi keltirilgan:

  • Jarayon umumiy xotiradan A qiymatini o'qiydi,
  • bu oldindan o'ylangan, jarayonga ruxsat berish yugurmoq,
  • umumiy xotira qiymatini oldindan belgilashdan oldin B qiymatiga va A ga qaytaradi,
  • yana ijro etishni boshlaydi, umumiy xotira qiymati o'zgarmaganligini ko'radi va davom etadi.

Garchi bajarilishini davom ettirishi mumkin, umumiy xotirada "yashirin" modifikatsiya tufayli xatti-harakatlar to'g'ri kelmasligi mumkin.

A-ni amalga oshirishda ABA muammosining odatiy hodisasi uchraydi qulfsiz ma'lumotlar tuzilishi. Agar biror narsa ro'yxatdan o'chirilsa, o'chirilsa va yangi narsa ajratilsa va ro'yxatga qo'shilsa, MRU xotirasini ajratish tufayli ajratilgan ob'ekt o'chirilgan ob'ekt bilan bir joyda bo'lishi odatiy holdir. Shunday qilib, yangi elementga ko'rsatgich ko'pincha ABA muammosini keltirib chiqaradigan eski elementga to'g'ri keladi.

Misollar

A yordamida ABA dasturiy ta'minotining misolini ko'rib chiqing qulfsiz suyakka:

/ * ABA muammosidan aziyat chekadigan sodda qulfsiz stak. * /sinf Yig'ma {  std::atom<Obj*> top_ptr;  //  // Yuqori ob'ektni ochadi va unga ko'rsatkichni qaytaradi.  //  Obj* Pop() {    esa (1) {      Obj* ret_ptr = top_ptr;      agar (!ret_ptr) qaytish nullptr;      // Oddiylik uchun, biz ushbu cheklov xavfsizligini ta'minlay olamiz deb taxmin qiling      // (ya'ni, boshqa biron bir ishchi bu orada to'plamni tashlamaganligi).      Obj* keyingi_ptr = ret_ptr->Keyingisi;      // Agar yuqori tugun hali ham ret bo'lsa, unda hech kim to'plamni o'zgartirmagan deb taxmin qiling.      // (ABA muammosi tufayli bu gap har doim ham to'g'ri kelmaydi)      // atomni yuqori bilan keyingisini almashtiring.      agar (top_ptr.taqqoslash_birjasi_juda(ret_ptr, keyingi_ptr)) {        qaytish ret_ptr;      }      // Stek o'zgardi, qayta boshlang.    }  }  //  // obj_ptr tomonidan belgilangan ob'ektni stekka suradi.  //  bekor Durang(Obj* obj_ptr) {    esa (1) {      Obj* keyingi_ptr = top_ptr;      obj_ptr->Keyingisi = keyingi_ptr;      // Agar yuqoridagi tugun hanuzgacha bo'lsa, unda hech kim to'plamni o'zgartirmagan deb taxmin qiling.      // (ABA muammosi tufayli bu gap har doim ham to'g'ri kelmaydi)      // Atomically top bilan obj.      agar (top_ptr.taqqoslash_birjasi_juda(keyingi_ptr, obj_ptr)) {        qaytish;      }      // Stek o'zgardi, qayta boshlang.    }  }};

Ushbu kod odatda muammolarni bir vaqtning o'zida kirishga to'sqinlik qilishi mumkin, ammo ABA muammolariga duch keladi. Quyidagi ketma-ketlikni ko'rib chiqing:

Dastlab stack o'z ichiga oladi yuqori → A → B → C

1-mavzu pop-ni ishga tushirishni boshlaydi:

ret = A; keyingi = B;

1-mavzu oldin biroz uzilib qoladi taqqoslash_birjasi_juda...

{ // 2-mavzu pop ishlaydi:  ret = A;  Keyingisi = B;  taqqoslash_birjasi_juda(A, B)  // Muvaffaqiyat, top = B  qaytish A;} // Endi stack top → B → C{ // 2-mavzu yana pop ishlaydi:  ret = B;  Keyingisi = C;  taqqoslash_birjasi_juda(B, C)  // Muvaffaqiyat, yuqori = C  qaytish B;} // Endi stack top → Co'chirish B;{ // 2-mavzu endi orqani stakka itaradi:  A->Keyingisi = C;  taqqoslash_birjasi_juda(C, A)  // Muvaffaqiyat, yuqori = A}

Endi stack yuqori → A → C

1-mavzu davom etganda:

taqqoslash_birjasi_juda (A, B)

Ushbu ko'rsatma muvaffaqiyatli bo'ladi, chunki u topadi yuqori == ret (ikkalasi ham A), shuning uchun u yuqoriga o'rnatadi (bu B). B o'chirilganligi sababli, dastur stekdagi birinchi elementga qarashga harakat qilganda bo'sh xotiraga ega bo'ladi. Bu erda ko'rsatilgandek C ++ da, bo'sh xotiraga kirish aniqlanmagan xatti-harakatlar: bu ishdan chiqishiga, ma'lumotlarning buzilishiga olib kelishi yoki hatto jimgina to'g'ri ishlashi kabi ko'rinishi mumkin. Bu kabi ABA xatolarini disk raskadrovka qilish qiyin bo'lishi mumkin.

Haqiqiy muammo "ABA" emas, ya'ni A qiymatining o'zgartirilganligi misolda muhim emas. Haqiqiy muammo B ro'yxatdan o'chirilganligi va uning xotirasi bo'shatilganligi bilan bog'liq. Agar A o'zgartirilmagan bo'lsa ham, ya'ni bog'langan ro'yxat birma-bir orqaga qarab C-> B-> A va tail-> A bilan bog'langan, ammo B o'chiriladi va boshqa ip bilan bo'shatiladi, yuqoridagi muammo haligacha mavjud. Bu yana bir muammoga olib keladi, ya'ni agar B boshqa bir qator bilan ro'yxatdan o'chirilsa, quyruq o'chirilgan B ga ishora qiladi. Shuning uchun "ABA muammosi" haqiqatan ham "Muammo B" dir, bu A bilan unchalik bog'liq emas.

Vaqtinchalik echimlar

Belgilangan davlat ma'lumotnomasi

Ko'rib chiqilayotgan miqdorga qo'shimcha "yorliq" yoki "shtamp" bitlarini qo'shish odatiy echimdir. Masalan, foydalanadigan algoritm taqqoslash va almashtirish ko'rsatgich manzilning past bitlaridan foydalanib, ko'rsatgich necha marta muvaffaqiyatli o'zgartirilganligini ko'rsatishi mumkin. Shu sababli, manzillar bir xil bo'lsa ham, keyingi taqqoslash va almashtirish muvaffaqiyatsiz bo'ladi, chunki teg bitlari mos kelmaydi. Bunga ba'zida ABAʹ deyiladi, chunki ikkinchi A birinchisidan bir oz farq qiladi. Bunday yorliqli davlat ma'lumotnomalari ham ishlatiladi tranzaksiya xotirasi. Garchi a belgilangan ko'rsatkich amalga oshirish uchun foydalanish mumkin, agar ikkita kenglikdagi CAS mavjud bo'lsa, alohida yorliq maydoniga afzallik beriladi.

Agar "teg" maydonini o'ralgan bo'lsa, ABAga qarshi kafolatlar endi o'zgarmaydi. Shu bilan birga, hozirda mavjud bo'lgan protsessorlarda va 60-bitli teglardan foydalangan holda dasturning ishlash muddati (ya'ni dasturni qayta ishga tushirmasdan) 10 yil bilan cheklangan bo'lsa, uni o'rab olish mumkin emasligi kuzatilgan; Bundan tashqari, amaliy maqsadlar uchun o'ralashga kafolat berish uchun odatda 40-48 bit yorliqqa ega bo'lish etarli deb ta'kidladilar. Zamonaviy protsessorlar (xususan, barcha zamonaviy x64 protsessorlar) 128-bitli CAS operatsiyalarini qo'llab-quvvatlashga moyil bo'lganligi sababli, bu ABAga qarshi qat'iy kafolatlar berishi mumkin.[1]

Qidiruv tugunlar

To'g'ri, ammo qimmat yondashuv - bu ma'lumotlar elementlari bo'lmagan oraliq tugunlardan foydalanish va shu bilan elementlar kiritilishi va olib tashlanishi bilan o'zgaruvchanlikni ta'minlash [Valois].

Kechiktirilgan melioratsiya

Boshqa yondashuv - olib tashlangan ma'lumotlar elementlarini qayta tiklashni kechiktirish. Melioratsiyani kechiktirishning usullaridan biri algoritmni an muhitida ishlatishdir avtomatik axlat yig'uvchi; Ammo bu erda muammo shundaki, agar GC qulflanmagan bo'lsa, demak ma'lumotlar tuzilmasining o'zi bo'lsa ham, umumiy tizim qulfsiz emas.

Melioratsiyani kechiktirishning yana bir usuli bu bir yoki bir nechtasini qo'llashdir xavf ko'rsatkichlari, aks holda ro'yxatda paydo bo'lishi mumkin bo'lmagan joylarga ko'rsatgich. Har bir xavf ko'rsatkichi davom etayotgan o'zgarishlarning oraliq holatini aks ettiradi; ko'rsatkichning mavjudligi keyingi sinxronizatsiyani ta'minlaydi [Dag Lea]. Xavf ko'rsatkichlari qulflanmagan, ammo faqat bitta ip uchun belgilangan elementlarning ko'pini ishlatishda kuzatishi mumkin.

Melioratsiyani kechiktirishning yana bir usuli - bu foydalanish o'qish-nusxalashni yangilash (RCU) Bu yangilanishni RCU o'qish uchun muhim qismiga qo'shib qo'yishni va keyin o'chirilgan ma'lumotlar elementlarini bo'shatishdan oldin RCU imtiyozli davrini kutishni o'z ichiga oladi. RCU-ni shu tarzda ishlatish har qanday o'chirilgan ma'lumotlar elementi, hozirda bajarilayotgan barcha operatsiyalar tugamaguncha paydo bo'lmasligini kafolatlaydi. RCU qulflanmagan, ammo barcha ish yuklariga mos kelmaydi.

Ba'zi arxitekturalar "kattaroq" atom operatsiyalarini ta'minlaydi, masalan, ikkitomonlama bog'langan ro'yxatdagi oldinga va orqaga yo'nalishlarni atomik ravishda yangilash mumkin; bu xususiyat arxitekturaga bog'liq bo'lsa-da, u, xususan, x86 / x64 arxitekturalari uchun mavjud (x86 64 bitli CASga, barcha zamonaviy x64 protsessorlar esa 128 bitli CASga ruxsat beradi) va IBM z / Arxitektura (bu 128 bitli CAS-ga imkon beradi).

Ba'zi arxitekturalar a yuk bog'langan, do'kon shartli do'kon faqat ko'rsatilgan joyda boshqa do'konlar mavjud bo'lmaganda amalga oshiriladigan ko'rsatma. Bu "xotira qiymati o'z ichiga olgan" tushunchasini "saqlash o'zgartirilgan" dan samarali ravishda ajratib turadi. Bunga misollar kiradi Alpha, MIPS, PowerPC, RISC-V va ARM (v6 va undan keyin).

Shuningdek qarang

Adabiyotlar

  • Dechev, Damian; Pirkelbauer, Piter; Stroustrup, Bjarne. "Qulfsiz dinamik o'lchamdagi massivlar". CiteSeerX  10.1.1.86.2680. Iqtibos jurnali talab qiladi | jurnal = (Yordam bering)
  • Dechev, Damian; Pirkelbauer, Piter; Stroustrup, Bjarne. "ABA muammosini tushunish va samarali oldini olish, deskriptorlar asosida blokirovka qilinmaydigan dizaynlarda" (PDF). Iqtibos jurnali talab qiladi | jurnal = (Yordam bering)