6. Cancarenzi nədir?
Paralellik Java-da bir neçə mövzuda işləmək üçün optimallaşdırılmış xüsusi sinifləri ehtiva edən sinif kitabxanasıdır. Bu siniflər paket şəklində toplanırjava.util.concurrent
. Funksionallığına görə onları sxematik olaraq aşağıdakı kimi bölmək olar: Paralel kolleksiyalarjava.util
- paketdən standart universal kolleksiyalardan çox yivli mühitdə daha səmərəli işləyən kolleksiyalar toplusu . Bütün kolleksiyaya girişi bloklayan əsas sarğı əvəzinə Collections.synchronizedList
məlumat seqmentlərində kilidlər istifadə olunur və ya gözləməsiz alqoritmlərdən istifadə edərək məlumatların paralel oxunması üçün iş optimallaşdırılır. Queues - çox iş parçacığı dəstəyi ilə bloklanmayan və bloklayan növbələr. Bloklanmayan növbələr, ipləri bloklamadan sürət və işləmə üçün nəzərdə tutulmuşdur. Bloklama növbələri bəzi şərtlər yerinə yetirilmədikdə, məsələn, növbə boş və ya daşdıqda və ya pulsuz "İstehlakçı" olmadıqda "İstehsalçı" və ya "İstehlakçı" mövzularını "yavaşlatmaq" lazım olduqda istifadə olunur. Sinxronizatorlar mövzuları sinxronlaşdırmaq üçün köməkçi proqramlardır. Onlar “paralel” hesablamada güclü silahdırlar. İcraçılar - mövzu hovuzları yaratmaq, asinxron tapşırıqları planlaşdırmaq və nəticələr əldə etmək üçün əla çərçivələri ehtiva edir. Kilidlərsynchronized
- əsaslarla müqayisədə alternativ və daha çevik ip sinxronizasiya mexanizmlərini təmsil wait
edir notify
. Atomika - primitivlər və istinadlar üzərində atom əməliyyatlarını dəstəkləyən siniflər. Mənbə:notifyAll
7. Kankarensidən hansı sinifləri bilirsiniz?
Bu sualın cavabı bu məqalədə mükəmməl şəkildə ifadə edilmişdir . Bütün bunları burada təkrar çap etməyin mənasını görmürəm, ona görə də yalnız qısaca tanış olmaq şərəfinə nail olduğum siniflərin təsvirini verəcəyəm. ConcurrentHashMap<K, V>Hashtable
- və bloklarından synhronized
fərqli olaraq HashMap
, məlumatlar açarların heşlərinə bölünmüş seqmentlər şəklində təqdim olunur. Nəticə etibarı ilə verilənlərə tək obyekt deyil, seqmentlər vasitəsilə daxil olur. Bundan əlavə, iteratorlar müəyyən bir müddət üçün məlumatları təmsil edir və atmırlar ConcurrentModificationException
. AtomicBoolean, AtomicInteger, AtomicLong, AtomicIntegerArray, AtomicLongArray - Əgər bir sinifdə bir sadə tipli dəyişənə girişi sinxronlaşdırmaq lazımdırsa nə olacaq int
? , ilə konstruksiyalardan istifadə edə bilərsiniz synchronized
və atom əməliyyatlarından istifadə edərkən set/get
, volatile
. Ancaq yeni dərslərdən istifadə etməklə daha da yaxşısını edə bilərsiniz Atomic*
. CAS-ın istifadəsi sayəsində bu siniflərlə əməliyyatlar vasitəsilə sinxronizasiya edildikdən daha sürətli olur synchronized/volatile
. Üstəlik, müəyyən miqdarda atom əlavə etmək, həmçinin artırma/azaltma üsulları var.
8. ConcurrentHashMap sinfi necə işləyir?
Tətbiq edilərkənConcurrentHashMap
Java tərtibatçıları aşağıdakı hash xəritəsinin tətbiqinə ehtiyac duydular:
- İp təhlükəsizliyi
- Bütün masaya daxil olarkən heç bir kilid yoxdur
- Oxuma əməliyyatını yerinə yetirərkən masa kilidlərinin olmaması arzu edilir
ConcurrentHashMap
aşağıdakılardır:
-
Xəritə elementləri
HashMap
Elementlərdən fərqli olaraqEntry
inConcurrentHashMap
kimi elan edilirvolatile
. Bu, həm də JMM- dəki dəyişikliklərə görə vacib bir xüsusiyyətdir .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]; } }
-
Hash funksiyası
ConcurrentHashMap
təkmilləşdirilmiş hashing funksiyasından da istifadə olunur.JDK 1.2 -də bunun necə olduğunu xatırlatmağa icazə verin
HashMap
:static int hash(int h) { h ^= (h >>> 20) ^ (h >>> 12); return h ^ (h >>> 7) ^ (h >>> 4); }
ConcurrentHashMap JDK 1.5 versiyası:
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); }
Niyə hash funksiyasını daha mürəkkəbləşdirməyə ehtiyac var? Hash xəritəsindəki cədvəllərin uzunluğu ikinin gücü ilə müəyyən edilir. İkili təsvirləri aşağı və yüksək mövqedə fərqlənməyən hash kodları üçün toqquşmalarımız olacaq. Hash funksiyasının mürəkkəbliyini artırmaq sadəcə bu problemi həll edir, xəritədə toqquşma ehtimalını azaldır.
-
Seqmentlər
Xəritə N müxtəlif seqmentə bölünür (standart olaraq 16, maksimum dəyər 16 bit ola bilər və ikinin gücüdür). Hər bir seqment xəritə elementlərinin iplə təhlükəsiz cədvəlidir. Seqmentlərin sayının artırılması modifikasiya əməliyyatlarını birdən çox seqmenti əhatə etməyə təşviq edəcək və icra zamanı bloklanma ehtimalını azaldacaq.
-
ConcurrencyLevel
Bu parametr yaddaş kartının istifadəsinə və kartdakı seqmentlərin sayına təsir göstərir.
Seqmentlərin sayı, concurrencyLevel-dən iki böyüklüyün ən yaxın gücü kimi seçiləcək. ConcurrencyLevel səviyyəsinin aşağı salınması mövzuların yazarkən xəritə seqmentlərini bloklamaq ehtimalını artırır. Göstəricinin həddindən artıq qiymətləndirilməsi yaddaşdan səmərəsiz istifadəyə səbəb olur. Yalnız bir mövzu xəritəni dəyişdirəcəksə və qalanları oxuyacaqsa, 1 dəyərindən istifadə etmək tövsiyə olunur.
-
Ümumi
Beləliklə, əsas üstünlüklər və tətbiq xüsusiyyətləri
ConcurrentHashMap
:- Xəritə oxşar
hashmap
interfeysə malikdir - Oxuma əməliyyatları kilid tələb etmir və paralel olaraq həyata keçirilir
- Yazma əməliyyatları çox vaxt bloklanmadan paralel olaraq da yerinə yetirilə bilər
- Yaradarkən, tələb olunan göstərilir
concurrencyLevel
, statistika oxunması və yazılması ilə müəyyən edilir value
Xəritə elementləri elan edilmiş dəyərə malikdirvolatile
- Xəritə oxşar
9. Lock sinfi nədir?
Paylaşılan mənbəyə girişi idarə etmək üçün sinxronlaşdırılmış operatora alternativ olaraq kilidlərdən istifadə edə bilərik. Kilidləmə funksiyası paketdədirjava.util.concurrent.locks
. Birincisi, mövzu paylaşılan mənbəyə daxil olmağa çalışır. Pulsuzdursa, ipə bir kilid qoyulur. İş başa çatdıqdan sonra paylaşılan resursun kilidi buraxılır. Resurs pulsuz deyilsə və artıq kilid yerləşdirilibsə, ip bu kilid buraxılana qədər gözləyir. Lock
Kilid sinifləri aşağıdakı metodları müəyyən edən interfeysi həyata keçirir :
void lock():
kilid alınana qədər gözləyirboolean tryLock():
kilid əldə etməyə çalışır; əgər kilid əldə edilərsə, doğru qaytarır . Kilid alınmazsa, false qaytarır . Metoddan fərqli olaraq,lock()
o, əgər mövcud deyilsə, kilid əldə etməyi gözləmirvoid unlock():
kilidi çıxarırCondition newCondition():
Condition
cari kilidlə əlaqəli olan obyekti qaytarır
lock()
və paylaşılan resurslarla işləməyi bitirdikdən sonra unlock()
kilidi buraxan üsul çağırılır. Obyekt Condition
bloklamağı idarə etməyə imkan verir. Bir qayda olaraq, kilidlərlə işləmək üçün ReentrantLock
paketdən bir sinif istifadə olunur.Bu java.util.concurrent.locks.
sinif interfeysi həyata keçirir Lock
. Nümunə olaraq kiçik bir proqramdan istifadə edərək Java Lock API-dən istifadə etməyə baxaq: Beləliklə, deyək ki, Resource
ip təhlükəsizliyi tələb olunmayan bir neçə ip üçün təhlükəsiz metod və metodlardan ibarət bir sinifimiz var.
public class Resource {
public void doSomething(){
// пусть здесь происходит работа с базой данных
}
public void doLogging(){
// потокобезопасность для логгирования нам не требуется
}
}
Runnable
İndi interfeysi həyata keçirən və sinif metodlarından istifadə edən bir sinif götürək 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();
}
}
İndi isə yuxarıdakı proqramı 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();
}
}
Proqramdan göründüyü kimi, tryLock()
ipin yalnız müəyyən bir müddət gözlədiyinə əmin olmaq üçün metoddan istifadə edirik. Obyektdə kilid əldə etməzsə, sadəcə daxil olur və çıxır. Başqa bir vacib məqam. Metod istisna atırsa try-finally
belə, kilidin buraxılmasını təmin etmək üçün blokdan istifadə etməlisiniz . Mənbələr:doSomething()
11. Muteks nədir?
Muteks mövzuları/prosesləri sinxronlaşdırmaq üçün xüsusi obyektdir. Bu, iki dövləti götürə bilər - məşğul və pulsuz. Sadələşdirmək üçün, mutex iki dəyər qəbul edən bir məntiqi dəyişəndir: məşğul (doğru) və pulsuz (yanlış). Bir mövzu obyektin müstəsna sahibliyini istədikdə, mutexini məşğul olaraq qeyd edir və onunla işləməyi bitirdikdə, mutexini pulsuz olaraq qeyd edir. Java-da hər bir obyektə mutex əlavə olunur. Yalnız Java maşınının mutexə birbaşa çıxışı var. Proqramçıdan gizlidir.12. Monitor nədir?
Monitor xüsusi mexanizmdir (kod parçası) - onunla düzgün işləməyi təmin edən mutex üzərində əlavədir. Axı, obyektin məşğul olduğunu qeyd etmək kifayət deyil, digər mövzuların məşğul obyektdən istifadə etməyə çalışmamasını da təmin etməliyik. Java-da monitor açar sözündən istifadə etməklə həyata keçirilirsynchronized
. Sinxronlaşdırılmış blok yazdığımız zaman Java kompilyatoru onu üç kod parçası ilə əvəz edir:
- Blokun əvvəlində
synchronized
mutex-i məşğul kimi qeyd edən kod əlavə olunur. - Blokun sonunda
synchronized
mutexi pulsuz olaraq qeyd edən kod əlavə olunur. - Blokdan əvvəl,
synchronized
mutexin məşğul olub-olmadığını yoxlayan kod əlavə olunur, sonra ip onun buraxılmasını gözləməlidir.
GO TO FULL VERSION