ReentrantLock jest nieuporządkowane , w przeciwieństwie do synchronized
konstrukcji - to znaczy, że nie trzeba używać strukturę blokową do blokowania, a nawet może posiadać blokadę całej metody. Przykład:
private ReentrantLock lock;
public void foo() {
...
lock.lock();
...
}
public void bar() {
...
lock.unlock();
...
}
Taki przepływ jest niemożliwy do przedstawienia za pomocą jednego monitora w synchronized
konstrukcji.
Oprócz tego ReentrantLock
obsługuje odpytywanie blokady i blokada przerywana czeka na obsługę limitu czasu . ReentrantLock
obsługuje także konfigurowalną politykę uczciwości , umożliwiając bardziej elastyczne planowanie wątków.
Konstruktor dla tej klasy akceptuje opcjonalny parametr uczciwości . Po ustawieniu true
, w sporze, zamki sprzyjają zapewnieniu dostępu do najdłużej czekającego wątku. W przeciwnym razie ta blokada nie gwarantuje żadnego konkretnego zamówienia dostępu. Programy korzystające z uczciwych blokad, do których dostęp ma wiele wątków, mogą wykazywać niższą ogólną przepustowość (tj. Są wolniejsze; często znacznie wolniejsze) niż programy korzystające z ustawień domyślnych, ale mają mniejsze rozbieżności w czasie w celu uzyskania blokad i zagwarantowania braku głodu. Należy jednak pamiętać, że uczciwość zamków nie gwarantuje rzetelności planowania wątków. Zatem jeden z wielu wątków korzystających z uczciwego zamka może uzyskać go wiele razy z rzędu, podczas gdy inne aktywne wątki nie postępują i obecnie nie utrzymują zamka. Należy również pamiętać, że nieterminowetryLock
metoda nie uwzględnia ustawienia uczciwości. Pomyślnie, jeśli blokada jest dostępna, nawet jeśli czekają inne wątki.
ReentrantLock
może być również bardziej skalowalny , działając znacznie lepiej przy większej rywalizacji. Możesz przeczytać więcej na ten temat tutaj .
Twierdzenie to zostało jednak zakwestionowane; zobacz następujący komentarz:
W teście blokady ponownego wysyłania nowa blokada jest tworzona za każdym razem, dlatego nie ma blokady wyłącznej, a dane wynikowe są nieprawidłowe. Ponadto łącze IBM nie oferuje kodu źródłowego dla bazowego testu porównawczego, więc niemożliwe jest określenie, czy test został przeprowadzony poprawnie.
Kiedy należy użyć ReentrantLock
s? Zgodnie z tym artykułem developerWorks ...
Odpowiedź jest dość prosta - użyj jej, gdy rzeczywiście potrzebujesz czegoś, co nie zapewnia synchronized
, na przykład oczekiwania na czas z blokadą, oczekiwania na blokadę przerywaną, blokady niestrukturalne, wiele zmiennych warunkowych lub odpytywanie blokad. ReentrantLock
ma również zalety skalowalności i należy go użyć, jeśli rzeczywiście występuje sytuacja, w której występuje duża rywalizacja, ale należy pamiętać, że zdecydowana większość synchronized
bloków prawie nigdy nie wykazuje żadnej rywalizacji, a tym bardziej wysokiej rywalizacji. Radziłbym rozwijać z synchronizacją, dopóki synchronizacja nie okaże się nieodpowiednia, zamiast zakładać, że „wydajność będzie lepsza”, jeśli użyjeszReentrantLock
. Pamiętaj, że są to zaawansowane narzędzia dla zaawansowanych użytkowników. (Naprawdę zaawansowani użytkownicy preferują najprostsze narzędzia, jakie mogą znaleźć, dopóki nie przekonają się, że proste narzędzia są nieodpowiednie). Jak zawsze, najpierw popraw to, a potem martw się, czy musisz to zrobić szybciej.