Po co używać Reentrantlocka, jeśli można użyć synchronized (this)?
Próbuję zrozumieć, co sprawia, że blokada w współbieżności jest tak ważna, jeśli można użyć synchronized (this)
. W poniższym kodzie mogę zrobić albo:
- zsynchronizował całą metodę lub zsynchronizował wrażliwy obszar(synchronized (this){...})
- lub zablokować podatny obszar kodu za pomocą blokady ReentrantLock .
Kod:
private final ReentrantLock lock = new ReentrantLock();
private static List<Integer> ints;
public Integer getResult(String name) {
.
.
.
lock.lock();
try {
if (ints.size()==3) {
ints=null;
return -9;
}
for (int x=0; x<ints.size(); x++) {
System.out.println("["+name+"] "+x+"/"+ints.size()+". values >>>>"+ints.get(x));
}
} finally {
lock.unlock();
}
return random;
}
5 answers
A ReentrantLock jest unstructured, w przeciwieństwie do synchronized
konstruktów-tzn. nie trzeba używać struktury blokowej do blokowania i można nawet trzymać blokadę między metodami. Przykład:
private ReentrantLock lock;
public void foo() {
...
lock.lock();
...
}
public void bar() {
...
lock.unlock();
...
}
Taki przepływ jest niemożliwy do reprezentowania przez pojedynczy monitor w konstrukcji synchronized
.
Poza tym, ReentrantLock
obsługuje blokowanie blokad i blokada przerywana czeka na wsparcie time-out. ReentrantLock
posiada również wsparcie dla konfigurowalne uczciwość Polityka , pozwalająca na bardziej elastyczne planowanie wątków.
Konstruktor dla tej klasy przyjmuje opcjonalny parametr . Po ustawieniu
true
, pod contention, blokuje faworyzowanie dostępu do najdłużej oczekiwanego wątku. W przeciwnym razie ta blokada nie gwarantuje żadnej konkretnej kolejności dostępu. Programy korzystające z uczciwych blokad, do których dostęp ma wiele wątków, mogą wyświetlać niższą ogólną przepustowość (tzn. są wolniejsze; często znacznie wolniejsze) niż te, które używają domyślnych ustawienie, ale mają mniejsze różnice w czasie, aby uzyskać zamki i zagwarantować brak głodu. Należy jednak pamiętać, że uczciwość blokad nie gwarantuje uczciwości planowania wątków. Tak więc, jeden z wielu wątków używających sprawiedliwej blokady może uzyskać ją wiele razy po kolei, podczas gdy inne aktywne wątki nie postępują i nie utrzymują blokady. Należy również zauważyć, że metoda untimedtryLock
nie honoruje ustawienia uczciwości. Uda się, jeśli blokada jest dostępna, nawet jeśli inne wątki są czekam.
ReentrantLock
may also be bardziej skalowalny, znacznie lepiej radzi sobie w Warunkach większych sporów. Możesz przeczytać więcej o tym tutaj .
To twierdzenie zostało jednak zakwestionowane; patrz następujący komentarz:
W teście blokady reentrant, za każdym razem tworzony jest nowy blok, więc nie ma wyłącznego blokowania, a wynikowe dane są nieprawidłowe. Ponadto IBM link nie oferuje kodu źródłowego dla bazowego benchmark więc jego niemożliwe do scharakteryzowania, czy test został nawet przeprowadzone poprawnie.
Kiedy należy stosować ReentrantLock
s? Zgodnie z tym artykułem developerWorks...
Odpowiedź jest dość prosta-używaj jej, gdy potrzebujesz czegoś, co zapewnia, że
synchronized
nie, jak timed lock waits, interruptible lock waits, non-block-structured locks, multiple condition variables lub lock polling.ReentrantLock
ma również zalety skalowalności i powinieneś z niej korzystać jeśli rzeczywiście masz sytuację, która wykazuje duże kontrowersje, ale pamiętaj, że zdecydowana większośćsynchronized
bloków prawie nigdy nie wykazuje żadnych kontrowersji, nie mówiąc już o wysokim sprzeciwie. Radzę rozwijać z synchronizacją, dopóki synchronizacja nie okaże się niewystarczająca, zamiast zakładać, że" wydajność będzie lepsza", jeśli użyjeszReentrantLock
. Pamiętaj, są to zaawansowane narzędzia dla zaawansowanych użytkowników. (I naprawdę zaawansowani użytkownicy wolą najprostsze narzędzia, które mogą znaleźć, dopóki nie są przekonany, że proste narzędzia są niewystarczające.) Jak zawsze, najpierw zrób to dobrze, a potem martw się o to, czy musisz zrobić to szybciej.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-09 16:03:50
Blokada reentrantowa pozwoli posiadaczowi blokady na wprowadzanie bloków kodu nawet po uzyskaniu blokady przez wprowadzenie innych bloków kodu. Blokada non-reentrant będzie miała blok uchwytu blokady na sobie, ponieważ musiałaby zwolnić blokadę otrzymaną z innego bloku kodu, aby ponownie uzyskać tę samą blokadę, aby wejść do zagnieżdżonej blokady wymagającej bloku kodu
public synchronized void functionOne() {
// do something
functionTwo();
// do something else
// redundant, but permitted...
synchronized(this) {
// do more stuff
}
}
public synchronized void functionTwo() {
// do even more stuff!
}
Rozszerzone możliwości blokady reentrant obejmują:-
- zdolność do posiadania więcej niż jednego warunku zmienna na monitor. Monitory, które używają zsynchronizowanego słowa kluczowego, mogą mieć tylko jedno. Oznacza to, że blokady reentrant obsługują więcej niż jedną kolejkę wait ()/notify ().
- możliwość uczynienia zamka "sprawiedliwym". "[Targi] zamki faworyzują dostęp do najdłużej czekającego wątku. W przeciwnym razie ta blokada nie gwarantuje żadnej konkretnej kolejności dostępu."Zsynchronizowane bloki są niesprawiedliwe.
- możliwość sprawdzenia, czy blokada jest utrzymywana.
- możliwość uzyskania listy wątków oczekujących na zamek.
Wady zamków reentrant to:-
Potrzeba dodania instrukcji importu. Trzeba zawijać blokady w try / finally block. To czyni go bardziej brzydkim niż zsynchronizowane słowo kluczowe. Zsynchronizowane słowo kluczowe Można umieścić w definicjach metod, co pozwala uniknąć konieczności posiadania bloku, który zmniejsza zagnieżdżanie.
Kiedy stosować:-
- ReentrantLock może być bardziej przydatny, jeśli chcesz zaimplementować wątek, który przemierza połączoną listę, blokując następny węzeł a następnie odblokowanie bieżącego węzła.
- zsynchronizowane słowo kluczowe jest odpowiednie w takich sytuacjach, jak blokowanie coarsening, zapewnia adaptacyjne obracanie, blokowanie stronnicze i możliwość usunięcia blokady poprzez analizę ucieczki. Te optymalizacje nie są obecnie zaimplementowane dla ReentrantLock.
Więcej informacji .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-23 06:28:15
ReentrantReadWriteLock
jest zamkiem specjalistycznym, podczas gdy synchronized(this)
jest zamkiem ogólnego przeznaczenia. Są podobne, ale nie do końca takie same.
Masz rację, że możesz użyć synchronized(this)
zamiast ReentrantReadWriteLock
, ale nie zawsze jest odwrotnie.
Jeśli chcesz lepiej zrozumieć, co sprawia, że ReentrantReadWriteLock
special poszukaj informacji na temat synchronizacji wątków producent-konsument.
Ogólnie można zapamiętać synchronizację całej metody i synchronizację ogólnego przeznaczenia (za pomocą słowo kluczowe synchronized
) może być używane w większości aplikacji bez myślenia zbytnio o semantyce synchronizacji, ale jeśli chcesz wycisnąć wydajność z kodu, może być konieczne zbadanie innych bardziej drobnoziarnistych lub specjalnych mechanizmów synchronizacji.
Przy okazji, użycie synchronized(this
) - i ogólnie blokowanie za pomocą instancji klasy publicznej - może być problematyczne, ponieważ otwiera Twój kod na potencjalne martwe blokady, ponieważ ktoś inny świadomie może spróbować aby zablokować obiekt w innym miejscu w programie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-12 16:21:54
Ze strony dokumentacji oracle o ReentrantLock :
Blokada wzajemnego wykluczania reentrant o tym samym podstawowym zachowaniu i semantyce, co ukryta blokada monitora, do której dostęp uzyskuje się przy użyciu zsynchronizowanych metod i instrukcji, ale z rozszerzonymi możliwościami.
Reentrantlock należy do wątku ostatnio blokującego, ale jeszcze go nie odblokowującego. Blokada wywołująca wątek powróci, z powodzeniem przejmując blokadę, gdy blokada jest nie należy do innego wątku. Metoda powróci natychmiast, jeśli bieżący wątek posiada już blokadę.
Konstruktor dla tej klasy przyjmuje opcjonalny parametr . Po ustawieniu true, blokuje favor przyznając dostęp do najdłużej czekającego wątku. W przeciwnym razie ta blokada nie gwarantuje żadnej konkretnej kolejności dostępu.
ReentrantLock najważniejsze cechy jak na to Artykuł
- możliwość przerwanego blokowania.
- możliwość timeout podczas oczekiwania na lock.
- moc tworzenia sprawiedliwego Locka.
- API do pobrania listy wątków oczekujących na blokadę.
- elastyczność, aby spróbować zablokować bez blokowania.
Możesz użyć ReentrantReadWriteLock.ReadLock, ReentrantReadWriteLock.Writelock pozwala na uzyskanie kontroli nad blokowaniem ziarnistym operacji odczytu i zapisu.
Zobacz też Artykuł napisany przez Benjamen na temat korzystania z różnych typów ReentrantLocks
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-07 08:27:02
Możesz użyć blokady reentrant z polityką uczciwości lub timeout, aby uniknąć głodu wątku. Możesz zastosować politykę uczciwości wątku. pomoże to uniknąć wątku czekającego wiecznie, aby dostać się do Twoich zasobów.
private final ReentrantLock lock = new ReentrantLock(true);
//the param true turns on the fairness policy.
"fairness policy" wybiera następny uruchomiony wątek do wykonania. Jest on oparty na priorytecie, czasie od ostatniego uruchomienia, bla bla
Także, Synchronize może blokować w nieskończoność, jeśli nie może uciec z bloku. Reentrantlock może mieć ustawiony limit czasu.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-18 18:59:15