6. Kankarenzi nima?
Concurrency - bu Java-dagi sinf kutubxonasi bo'lib, u bir nechta mavzularda ishlash uchun optimallashtirilgan maxsus sinflarni o'z ichiga oladi. Ushbu sinflar paketga yig'iladijava.util.concurrent
. Funksionalligiga ko‘ra ularni sxematik tarzda quyidagicha ajratish mumkin: Concurrent Collectionsjava.util
– to‘plamdagi standart universal to‘plamlarga qaraganda ko‘p tarmoqli muhitda samaraliroq ishlaydigan to‘plamlar to‘plami . Butun to'plamga kirishni bloklaydigan asosiy o'ram o'rniga Collections.synchronizedList
ma'lumotlar segmentlarida qulflar qo'llaniladi yoki kutishsiz algoritmlar yordamida ma'lumotlarni parallel o'qish uchun ish optimallashtiriladi. Navbatlar - ko'p tarmoqli qo'llab-quvvatlanadigan bloklanmaydigan va blokirovka qiluvchi navbatlar. Bloklanmagan navbatlar iplarni blokirovka qilmasdan tezlik va ishlash uchun mo'ljallangan. Bloklash navbatlari, agar ba'zi shartlar bajarilmasa, masalan, navbat bo'sh yoki to'lib ketgan bo'lsa yoki bepul "Iste'molchi" bo'lmasa, "Ishlab chiqaruvchi" yoki "Iste'molchi" iplarini "sekinlashtirish" kerak bo'lganda qo'llaniladi. Sinxronizatorlar iplarni sinxronlashtirish uchun yordamchi yordamchi dasturlardir. Ular "parallel" hisoblashda kuchli quroldir. Ijrochilar - ip hovuzlarini yaratish, asinxron vazifalarni rejalashtirish va natijalarni olish uchun ajoyib ramkalarni o'z ichiga oladi. Qulflar - asosiy synchronized
bo'lganlarga nisbatan muqobil va yanada moslashuvchan ip sinxronlash mexanizmlarini ifodalaydi . Atomika - ibtidoiy va havolalar ustida atom operatsiyalarini qo'llab-quvvatlaydigan sinflar. Manba:wait
notify
notifyAll
7. Kankarensidan qanday sinflarni bilasiz?
Bu savolga javob ushbu maqolada to'liq bayon etilgan . Bu erda hammasini qayta nashr etishdan ma'no ko'rmayapman, shuning uchun men qisqacha tanishish sharafiga muyassar bo'lgan sinflarning tavsifini beraman. ConcurrentHashMap<K, V> -Hashtable
va bloklaridan synhronized
farqli o'laroq HashMap
, ma'lumotlar kalitlar xeshlariga bo'lingan segmentlar shaklida taqdim etiladi. Natijada, ma'lumotlarga bitta ob'ekt emas, balki segmentlar orqali kirish mumkin. Bundan tashqari, iteratorlar ma'lum bir vaqt oralig'idagi ma'lumotlarni ifodalaydi va tashlamaydi ConcurrentModificationException
. AtomicBoolean, AtomicInteger, AtomicLong, AtomicIntegerArray, AtomicLongArray - Agar sinfda bitta oddiy o'zgaruvchiga kirishni sinxronlashtirish kerak bo'lsa-chi int
? Siz bilan konstruksiyalardan foydalanishingiz mumkin synchronized
va atom operatsiyalaridan foydalanganda set/get
, volatile
. Lekin siz yangi sinflardan foydalangan holda yanada yaxshi ish qilishingiz mumkin Atomic*
. CAS-dan foydalanish tufayli, ushbu sinflar bilan operatsiyalar orqali sinxronlashtirilgandan ko'ra tezroq synchronized/volatile
. Bundan tashqari, ma'lum miqdorda atom qo'shish, shuningdek oshirish/kamaytirish usullari mavjud.
8. ConcurrentHashMap klassi qanday ishlaydi?
Uni joriy qilish vaqtidaConcurrentHashMap
Java dasturchilariga quyidagi xesh-xaritani amalga oshirish kerak edi:
- Ip xavfsizligi
- Unga kirishda butun stolda hech qanday qulf yo'q
- O'qish operatsiyasini bajarishda stol qulflari bo'lmasligi ma'qul
ConcurrentHashMap
quyidagilardan iborat:
-
Xarita elementlari
Elementlardan farqli o'laroq
HashMap
,Entry
inConcurrentHashMap
sifatida e'lon qilinadivolatile
. Bu JMM dagi o'zgarishlar tufayli ham muhim xususiyatdir .static final class HashEntry<K, V> { final K key; final int hash; volatile V value; final HashEntry<K, V> next; HashEntry(K key, int hash, HashEntry<K, V> next, V value) { this .key = key; this .hash = hash; this .next = next; this .value = value; } @SuppressWarnings("unchecked") static final <K, V> HashEntry<K, V>[] newArray(int i) { return new HashEntry[i]; } }
-
Xesh funktsiyasi
ConcurrentHashMap
takomillashtirilgan xeshlash funksiyasidan ham foydalaniladi.HashMap
JDK 1.2 da qanday bo'lganini eslatib o'taman :static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
ConcurrentHashMap JDK 1.5 versiyasi:
private static int hash(int h) { h += (h << 15) ^ 0xffffcd7d; h ^= (h >>> 10); h += (h << 3); h ^= (h >>> 6); h += (h << 2) + (h << 14); return h ^ (h >>> 16); }
Nega hash funktsiyasini murakkabroq qilish kerak? Xesh xaritasidagi jadvallar uzunligi ikki kuch bilan belgilanadi. Ikkilik ko'rinishlari past va yuqori holatda farq qilmaydigan xesh kodlari uchun bizda to'qnashuvlar bo'ladi. Xash funktsiyasining murakkabligini oshirish bu muammoni hal qiladi va xaritadagi to'qnashuvlar ehtimolini kamaytiradi.
-
Segmentlar
Xarita N xil segmentga bo'lingan (sukut bo'yicha 16 ta, maksimal qiymat 16 bit bo'lishi mumkin va ikkita quvvat). Har bir segment xarita elementlarining ip-xavfsiz jadvalidir. Segmentlar sonini ko'paytirish bir nechta segmentlarni qamrab olish uchun o'zgartirish operatsiyalarini rag'batlantiradi va ish vaqtida blokirovka qilish ehtimolini kamaytiradi.
-
ConcurrencyLevel
Ushbu parametr xotira kartasidan foydalanish va kartadagi segmentlar soniga ta'sir qiladi.
Segmentlar soni concurrencyLevel dan kattaroq ikkining eng yaqin kuchi sifatida tanlanadi. ConcurrencyLevel darajasini pasaytirish, yozish paytida mavzular xarita segmentlarini bloklash ehtimolini oshiradi. Ko'rsatkichni ortiqcha baholash xotiradan samarasiz foydalanishga olib keladi. Agar faqat bitta ip xaritani o'zgartirsa va qolganlari o'qisa, 1 qiymatidan foydalanish tavsiya etiladi.
-
Jami
Shunday qilib, asosiy afzalliklari va amalga oshirish xususiyatlari
ConcurrentHashMap
:- Xaritada shunga o'xshash
hashmap
o'zaro ta'sir interfeysi mavjud - O'qish operatsiyalari qulflarni talab qilmaydi va parallel ravishda amalga oshiriladi
- Yozish operatsiyalari ko'pincha blokirovkasiz parallel ravishda ham amalga oshirilishi mumkin
- Yaratishda kerakli ko'rsatiladi
concurrencyLevel
, o'qish va yozish statistikasi bilan aniqlanadi value
Xarita elementlari deb e'lon qilingan qiymatga egavolatile
- Xaritada shunga o'xshash
9. Lock sinfi nima?
Umumiy manbaga kirishni nazorat qilish uchun biz sinxronlashtirilgan operatorga muqobil qulflardan foydalanishimiz mumkin. Qulflash funksiyasi ichida paketlanganjava.util.concurrent.locks
. Birinchidan, mavzu umumiy manbaga kirishga harakat qiladi. Agar u bepul bo'lsa, u holda ipga qulf o'rnatiladi. Ish tugagandan so'ng, umumiy resursdagi qulf chiqariladi. Agar resurs bo'sh bo'lmasa va unga allaqachon qulf o'rnatilgan bo'lsa, ip bu qulf bo'shatilguncha kutadi. Lock
Qulflash sinflari quyidagi usullarni belgilaydigan interfeysni amalga oshiradi :
void lock():
qulf olinmaguncha kutadiboolean tryLock():
qulf olishga harakat qiladi; agar qulf olinsa, u true ni qaytaradi . Agar qulf olinmasa, u false ni qaytaradi . Usuldan farqli o'laroq,lock()
agar mavjud bo'lmasa, u qulfni olishni kutmaydivoid unlock():
qulfni olib tashlaydiCondition newCondition():
Condition
joriy qulf bilan bog'langan ob'ektni qaytaradi
lock()
usul chaqiriladi . unlock()
Ob'ekt Condition
sizga blokirovka qilishni boshqarish imkonini beradi. Qoida tariqasida qulflar bilan ishlash uchun ReentrantLock
paketdagi sinfdan foydalaniladi.Ushbu java.util.concurrent.locks.
sinf interfeysni amalga oshiradi Lock
. Misol tariqasida kichik dastur yordamida Java Lock API-dan foydalanishni ko'rib chiqaylik: Aytaylik, bizda Resource
ip xavfsizligi talab qilinmaydigan bir nechta ip-xavfsiz usullar va usullardan iborat sinf mavjud.
public class Resource {
public void doSomething(){
// пусть здесь происходит работа с базой данных
}
public void doLogging(){
// потокобезопасность для логгирования нам не требуется
}
}
Runnable
Endi interfeysni amalga oshiradigan va sinf usullaridan foydalanadigan sinfni olaylik Resource
.
public class SynchronizedLockExample implements Runnable{
// экземпляр класса Resource для работы с методами
private Resource resource;
public SynchronizedLockExample(Resource r){
this.resource = r;
}
@Override
public void run() {
synchronized (resource) {
resource.doSomething();
}
resource.doLogging();
}
}
Endi yuqoridagi dasturni o'rniga Lock API yordamida qayta yozamiz synchronized
.
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
// класс для работы с Lock API. Переписан с приведенной выше программы,
// но уже без использования ключевого слова synchronized
public class ConcurrencyLockExample implements Runnable{
private Resource resource;
private Lock lock;
public ConcurrencyLockExample(Resource r){
this.resource = r;
this.lock = new ReentrantLock();
}
@Override
public void run() {
try {
// лочим на 10 секунд
if(lock.tryLock(10, TimeUnit.SECONDS)){
resource.doSomething();
}
} catch (InterruptedException e) {
e.printStackTrace();
}finally{
//убираем лок
lock.unlock();
}
// Для логгирования не требуется потокобезопасность
resource.doLogging();
}
}
Dasturdan ko'rinib turibdiki, biz tryLock()
ipning faqat ma'lum bir vaqtni kutishiga ishonch hosil qilish uchun usuldan foydalanamiz. Agar u ob'ektda qulfni olmagan bo'lsa, u shunchaki jurnalga kiradi va chiqadi. Yana bir muhim nuqta. Agar usul istisno bo'lsa try-finally
ham, qulf bo'shatilishini ta'minlash uchun siz blokdan foydalanishingiz kerak . Manbalar:doSomething()
11. Muteks nima?
Muteks - bu mavzularni/jarayonlarni sinxronlashtirish uchun maxsus ob'ekt. Bu ikki holatni olishi mumkin - band va bepul. Soddalashtirish uchun mutex bu ikki qiymatni qabul qiladigan mantiqiy o'zgaruvchidir: band (to'g'ri) va bepul (noto'g'ri). Agar ip ob'ektga eksklyuziv egalik qilishni xohlasa, u o'z mutexini band deb belgilaydi va u bilan ishlashni tugatgandan so'ng, u mutexni bepul deb belgilaydi. Muteks Java-dagi har bir ob'ektga biriktirilgan. Muteksga faqat Java mashinasi to'g'ridan-to'g'ri kirish huquqiga ega. U dasturchidan yashiringan.12. Monitor nima?
Monitor - bu maxsus mexanizm (kod bo'lagi) - mutex ustidagi qo'shimcha, u bilan to'g'ri ishlashni ta'minlaydi. Oxir oqibat, ob'ekt band ekanligini belgilashning o'zi etarli emas, biz boshqa iplar band ob'ektdan foydalanishga harakat qilmasligini ham ta'minlashimiz kerak. Java-da monitor kalit so'zi yordamida amalga oshiriladisynchronized
. Sinxronlashtirilgan blokni yozganimizda, Java kompilyatori uni uchta kod bilan almashtiradi:
- Blokning boshida
synchronized
mutexni band deb belgilaydigan kod qo'shiladi. - Blokning oxirida
synchronized
mutexni bepul deb belgilaydigan kod qo'shiladi. - Blokdan oldin,
synchronized
mutex band yoki yo'qligini tekshiradigan kod qo'shiladi, keyin ip uning chiqarilishini kutishi kerak.
GO TO FULL VERSION