JavaRush /Kurslar /All lectures for UZ purposes /Java Concurrency Kutubxonasi

Java Concurrency Kutubxonasi

All lectures for UZ purposes
Daraja, Dars
Mavjud

Java'da Ko'pprogrrammalash

Java Virtual Machine parallel hisob-kitoblarni qo'llab-quvvatlaydi. Barcha hisob-kitoblar bitta yoki bir necha oqim kontekstida bajarilishi mumkin. Biz bir nechta oqimlar uchun bitta resurs yoki ob'ektga kirishni osongina sozlay olamiz, shuningdek, alohida kod blokini bajarishga oqimni sozlay olamiz.

Har qanday dasturchiga resurslarga bir nechta oqimlar ajratilganida, o'qish va yozish operatsiyalarida oqimlar bilan ishlashni sinxronizatsiya qilish zarur.

Bu muhim, chunki resursga murojaat qilayotganda sizda dolzarb ma'lumotlar bo'lishi kerak, to boshqa bir oqim ularni o'zgartirishi mumkin va siz eng yangi ma'lumotlarni olasiz. Hatto bank hisobini misol qilib olsak, unga pul tushmaguncha siz ulardan foydalana olmaysiz, shuning uchun har doim dolzarb ma'lumotlarga ega bo'lishingiz muhim. Java'da oqimlarni sinxronizatsiya qilish va ularni boshqarish uchun maxsus sinflar mavjud.

Oqimlar Ob'ektlari

Hammasi asosiy (bosh) oqimdan boshlanadi, ya'ni dasturingizda minimal bir bajariladigan oqim mavjud. Bosh oqim boshqa oqimlarni Callable yoki Runnable yordamida yaratishi mumkin. Yaratilish faqat qaytariladigan natija bilan farqlanadi, Runnable natija qaytarmaydi va tekshiriladigan istisnoni chiqarib yuborolmaydi. Shu sababdan sizda fayllar bilan samarali ishlash imkoniyati paydo bo'ladi, lekin bu juda xavfli va ehtiyot bo'lish kerak.

Bundan tashqari, oqimning bajarilishini markaziy protsessorning alohida yadrosida rejalashtirish imkoniyati mavjud. Tizim oqimlar orasida osongina o'ta oladi va to'g'ri sozlamalar bilan muayyan oqimni bajaradi: ya'ni, birinchi navbatda ma'lumotlarni o'qiydigan oqim bajariladi, ma'lumotlar paydo bo'lgandan keyin, biz ularni tasdiqlash uchun javobgar oqimga o'tkazamiz, shundan so'ng ma'lumotlarni qayta ishlashning biron bir biznes-loyihasi uchun javob beradigan oqimga va yangitdan ularni qayta yozuvchi oqimga beramiz. Bunday vaziyatda 4 ta oqim ketma-ketlikda ma'lumotlarni qayta ishlaydi va hammasi bir oqimdan ko'ra tezroq ishlaydi. Har bir shunday oqim OSning mavjud oqimiga aylanadi, qanday usulda ularni amalga oshirishi esa JVMning amalga oshirishiga bog'liq.

Thread sinfi oqimlarni yaratish va ular bilan ishlash uchun xizmat qiladi. Unda boshqarishning standart mexanizmlari mavjud, shuningdek, abstrakt, masalan, java.util.concurrent sinflarida va kolleksiyalarida bo'ladi.

Java'da Oqimlarni Sinxronizatsiya Qilish

Aloqa ob'ektlarga kirishni taqsimlash orqali ta'minlanadi. Bu juda samarali, lekin shu bilan birga ishlashda xato qilish juda oson. Xatolar ikki xil bo'ladi: thread interference — boshqa oqim sizning oqimingizga aralashganda va memory consistency errors — xotira konsistentsiyasida. Ushbu xatolarni hal qilish va oldini olish uchun bizning turli sinxronizatsiya usullarimiz mavjud.

Java'da oqimlarni sinxronizatsiya qilish monitorlar bilan amalga oshiriladi, bu yuqori darajadagi mexanizm bo'lib, bir vaqtning o'zida faqat bitta oqimni kod blokini bajarishga imkon beradi, bu monitor bilan himoyalangan. Monitorlarning xatti-harakatlari blokirovkalar nuqtai nazaridan ko'rib chiqiladi; bitta monitor — bitta blokirovka.

Sinxronizatsiya bir necha muhim jihatlarni o'z ichiga oladi, ularga diqqat qilish kerak. Birinchi nuqta — bu o'zaro istisno (mutual exclusion) — faqat bitta oqim monitorga ega bo'lishi mumkin, shu sababli monitorning sinxronizatsiyasi, bir oqim sinxronizatsiyalangan blokka kirishi bilan hech qaysi boshqa oqim bu monitordagi blokka kira olmaydi, birinchi oqim sinxronizatsiyalangan blokdan chiqmaguncha. Ya'ni, bir vaqtning o'zida bir nechta oqim bir sinxronizatsiyalangan blokka kira olmaydi.

Lekin sinxronizatsiya — bu faqat o'zaro istisno emas. Sinxronizatsiya ma'lumotlar, xotiraga yozilgan yoki sinxronizatsiyalangan blok ichida bo'lgan ma'lumotlar, boshqa oqimlar uchun ko'rinadiganligini ta'minlaydi, ular ham xuddi shu monitorda sinxronizatsiyalanadi. Blokdan chiqqandan so'ng biz monitordan chiqamiz va boshqa oqim uni qo'lga olib, ushbu kod blokini bajarishni boshlashga imkon beradi.

Agar yangi oqim monitorga kirsa, biz ushbu kod blokini bajarish imkoniyatini olamiz va bu vaqtda o'zgaruvchilar asosiy xotiradan yuklanadi. Shunda biz barcha yozuvlarni ko'ra olamiz, ular avvalgi monitordan chiqish (release) paytida ko'rinadigan bo'lgan.

Maydonni alohida o'qish yoki yozish atomar bajariladi, agar maydon volatile deb e'lon qilingan bo'lsa (long va double uchun bu muhim) yoki unga barcha murojaatlar bir xil blokirovka bilan himoyalangan bo'lsa. Sinxronizatsiya bo'lmasa, tartibni o'zgartirish (reordering) effektlari yuz berishi mumkin: noto'g'ri sinxronizatsiya qilingan dasturda bir oqim boshqa oqim kiritgan o'zgarishlarni kutilmagan tartibda ko'rishi mumkin.

O'zaro istisno va oqimlarni sinxronizatsiya qilish efekti, ya'ni ularning to'g'ri ishlashiga faqat sinxronizatsiyalangan blok yoki metodga kirish orqali erishiladi, bu avtomatik ravishda blokirovkani olishdir yoki blokirovkani ochiq usulda olish orqali. Buning haqida biz quyida gaplashamiz. Ikkala usul ham xotirangizga ta'sir ko'rsatadi va volatile o'zgaruvchilar bilan ishlashni unutmang.

Java'dagi Volatile Maydonlari

volatile kalit so'zi ko'rinuvchanlik muammosini hal qiladi. Agar oqim volatile maydonga qiymat yozgan bo'lsa, keyin bu maydonni o'qigan har qanday boshqa oqim eskirgan nusxani emas, yangi qiymatni ko'radi.

Xotiraga ta'siri bo'yicha volatile maydonga yozish monitorni bo'shatishga, o'qish esa uni qo'lga olishga o'xshaydi. A oqimi volatile maydonga yozishdan oldin yozgan hamma narsani B oqimi, agar u bu maydondan yozilgan qiymatni o'qigan bo'lsa, kafolatli ravishda ko'radi. Bu munosabat happens-before («oldin bajariladi») deb ataladi.

volatile maydonni alohida o'qish yoki yozish atomar, shu jumladan long va double uchun ham. Ammo tarkibiy amallar, masalan count++ (o'qish, oshirish, yozish), atomar emas: qadamlar orasiga boshqa oqim aralashishi mumkin va oshirishlarning bir qismi yo'qoladi. volatile o'zaro istisnoni ta'minlamaydi. Tarkibiy amal atomar bajarilishi uchun synchronized, Lock yoki AtomicInteger, AtomicLong va h.k. sinflar kerak.

Java Concurrent

Agar siz super samarali va ko'pprogrrammali ilova yaratmoqchi bo'lsangiz, JavaConcurrent kutubxonasidan sinflarni ishlatishingiz lozim, ular java.util.concurrent paketida joylashgan.

Kutubxona juda keng va turli xil funksiyalarga ega, shuning uchun ichida nima borligini ko'rib chiqamiz va ba'zi modullarga bo'linamiz:

Java Concurrent

Concurrent Collections — ko'pprogrrammali muhitda ishlash uchun kolleksiyalar jamlanmasi. Kolleksiya bo'ylab kirishni bloklaydigan asosiy Collections.synchronizedList o'rniga, ma'lumot segmentlari bo'yicha blokirovka yoki parallel ma'lumotlarni o'qish uchun kutish-bo'lmagan algoritmlar ishlatiladi.

Queues — ko'pprogrrammali muhitda ishlash uchun blokirovka qilinmagan va blokirovka qilingan navbatlar. Blokirovka qilinmagan navbatlar tezlikka va oqimlarni bloklamasdan ishlashga yo'naltirilgan. Blokirovka qilingan navbatlar oqimlarni "to'xtatib turish" uchun mos keladi, ya'ni Producer yoki Consumer oqimlaridan biri talab etilmagan sharoitlar mavjud bo'lganda, navbat bo'sh yoki to'lgan yoki Consumer mavjud emas.

Synchronizers — oqimlarni sinxronizatsiya qilish uchun yordamchi vositalar. Ular "parallel" hisob-kitoblardagi qudratli qurol.

Executors — oqim havolasini qulay va oson yaratish uchun ramka, asinxron vazifalarni rejalashtirishni natijalarni olish bilan oson sozlash imkoniyatini beradi.

Locks — bazaviy synchronized, wait, notify, notifyAll bilan solishtirganda oqimlarni sinxronizatsiya qilish uchun ko'plab moslashuvchan mexanizmlar.

Atomics — primitivlar va havolalar ustida atomar amallarni qo'llab-quvvatlaydigan sinflar.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION