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:

  1. zsynchronizował całą metodę lub zsynchronizował wrażliwy obszar(synchronized (this){...})
  2. 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;
}
Author: rouble, 2012-08-06

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 untimed tryLock 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ć ReentrantLocks? 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żyjesz ReentrantLock. 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.

 391
Author: oldrinb,
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ą:-

  1. 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 ().
  2. 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.
  3. możliwość sprawdzenia, czy blokada jest utrzymywana.
  4. 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ć:-

  1. 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.
  2. 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 .

 17
Author: Akash5288,
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.

 12
Author: Mike Dinescu,
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.

  1. 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ę.

  2. 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ł

  1. możliwość przerwanego blokowania.
  2. możliwość timeout podczas oczekiwania na lock.
  3. moc tworzenia sprawiedliwego Locka.
  4. API do pobrania listy wątków oczekujących na blokadę.
  5. 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

 6
Author: Ravindra babu,
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.

 0
Author: j2emanue,
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