Jaka jest różnica między używaniem klas opakowujących,, SynchronizedMap
na a HashMap
i ConcurrentHashMap
?
Czy jest to po prostu w stanie zmodyfikować HashMap
podczas iteracji ( ConcurrentHashMap
)?
Jaka jest różnica między używaniem klas opakowujących,, SynchronizedMap
na a HashMap
i ConcurrentHashMap
?
Czy jest to po prostu w stanie zmodyfikować HashMap
podczas iteracji ( ConcurrentHashMap
)?
Odpowiedzi:
Zsynchronizowane HashMap
:
Każda metoda jest synchronizowana za pomocą blokady na poziomie obiektu. Zatem metody get i put na synchMap uzyskują blokadę.
Blokowanie całej kolekcji to narzut wydajności. Podczas gdy jeden wątek trzyma się blokady, żaden inny wątek nie może korzystać z kolekcji.
ConcurrentHashMap
został wprowadzony w JDK 5.
Nie ma blokowania na poziomie obiektu. Blokowanie jest znacznie dokładniejsze. W przypadku a ConcurrentHashMap
, zamki mogą znajdować się na poziomie wiadra hashmap.
Efektem blokowania niższego poziomu jest to, że możesz mieć jednocześnie czytających i piszących, co nie jest możliwe w przypadku zsynchronizowanych kolekcji. Prowadzi to do znacznie większej skalowalności.
ConcurrentHashMap
nie zgłasza a, ConcurrentModificationException
jeśli jeden wątek próbuje go zmodyfikować, podczas gdy inny go iteruje.
Ten artykuł Java 7: HashMap vs ConcurrentHashMap to bardzo dobra lektura. Wysoce rekomendowane.
ConcurrentHashMap
„s size()
wynik mógłby być nieaktualne. size()
może zwracać przybliżenie zamiast dokładnej liczby, zgodnie z książką „Java Concurrency in Practice”. Dlatego tę metodę należy stosować ostrożnie.
Krótka odpowiedź:
Obie mapy są bezpiecznymi wątkowo implementacjami Map
interfejsu. ConcurrentHashMap
jest zaimplementowany w celu zwiększenia przepustowości w przypadkach, w których oczekiwana jest wysoka współbieżność.
Artykuł Briana Goetza na temat stojącej za nim idei ConcurrentHashMap
jest bardzo dobrą lekturą. Wysoce rekomendowane.
Map m = Collections.synchronizedMap(new HashMap(...));
docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
ConcurrentHashMap
jest bezpieczny wątkowo bez synchronizacji całej mapy. Odczyty mogą następować bardzo szybko, gdy zapis jest wykonywany z blokadą.
Możemy osiągnąć bezpieczeństwo wątków, używając zarówno ConcurrentHashMap, jak i synchronisedHashmap. Ale jest spora różnica, jeśli spojrzeć na ich architekturę.
Utrzyma blokadę na poziomie obiektu. Więc jeśli chcesz wykonać jakąkolwiek operację, taką jak put / get, musisz najpierw zdobyć blokadę. W tym samym czasie inne wątki nie mogą wykonywać żadnej operacji. Tak więc w danym momencie może na tym działać tylko jeden wątek. Więc czas oczekiwania wydłuży się tutaj. Możemy powiedzieć, że wydajność jest stosunkowo niska w porównaniu z ConcurrentHashMap.
Utrzyma blokadę na poziomie segmentu. Ma 16 segmentów i domyślnie utrzymuje poziom współbieżności 16. Zatem jednocześnie 16 wątków może działać na ConcurrentHashMap. Co więcej, operacja odczytu nie wymaga blokady. Zatem dowolna liczba wątków może wykonać na nim operację pobierania.
Jeśli wątek 1 chce wykonać operację umieszczania w segmencie 2, a wątek 2 chce wykonać operację umieszczania w segmencie 4, jest to tutaj dozwolone. Oznacza to, że 16 wątków może jednocześnie wykonywać operacje aktualizacji (wstawiania / usuwania) na ConcurrentHashMap.
Aby czas oczekiwania był tutaj krótszy. Dlatego wydajność jest relatywnie lepsza niż synchronizowana mapa Hashmap.
Oba są zsynchronizowaną wersją HashMap, z różnicą w ich podstawowej funkcjonalności i wewnętrznej strukturze.
ConcurrentHashMap składa się z wewnętrznych segmentów, które koncepcyjnie można postrzegać jako niezależne HashMapy. Wszystkie takie segmenty mogą być blokowane przez oddzielne wątki podczas wykonywania dużej liczby jednoczesnych operacji. Tak więc wiele wątków może pobierać / umieszczać pary klucz-wartość z ConcurrentHashMap bez blokowania / oczekiwania na siebie. Jest to realizowane w celu zwiększenia przepustowości.
natomiast
Collections.synchronizedMap () , otrzymujemy zsynchronizowaną wersję HashMap i dostęp do niej jest blokowany. Oznacza to, że jeśli wiele wątków spróbuje uzyskać dostęp do synchronizedMap w tym samym czasie, będą mogły pobierać / umieszczać pary klucz-wartość pojedynczo w zsynchronizowany sposób.
ConcurrentHashMap
wykorzystuje drobnoziarnisty mechanizm blokujący znany jako lock stripping
umożliwiający większy stopień wspólnego dostępu. Dzięki temu zapewnia lepszą współbieżność i skalowalność .
Również zwrócone iteratory ConcurrentHashMap
są słabo spójne zamiast szybkich niepowodzeń techniki używanej przez Synchronized HashMap.
Metody SynchronizedMap
wstrzymują blokadę obiektu, podczas gdy w nich ConcurrentHashMap
istnieje koncepcja „blokowania paska”, w której zamki są utrzymywane na pojemnikach z zawartością. W ten sposób ulepszona skalowalność i wydajność.
ConcurrentHashMap:
1) Obie mapy są bezpiecznymi wątkowo implementacjami interfejsu Map.
2) ConcurrentHashMap jest zaimplementowany w celu zwiększenia przepustowości w przypadkach, w których oczekiwana jest wysoka współbieżność.
3) Nie ma blokady na poziomie obiektu.
Zsynchronizowana mapa skrótów:
1) Każda metoda jest synchronizowana za pomocą blokady na poziomie obiektu.
ConcurrentHashMap umożliwia jednoczesny dostęp do danych. Cała mapa podzielona jest na segmenty.
Przeczytaj operację tj. get(Object key)
nie jest zsynchronizowany nawet na poziomie segmentu.
Ale operacje zapisu tj. remove(Object key), get(Object key)
uzyskać blokadę na poziomie segmentu. Tylko część całej mapy jest zablokowana, inne wątki nadal mogą odczytywać wartości z różnych segmentów poza zablokowanym.
Z drugiej strony, SynchronizedMap uzyskuje blokadę na poziomie obiektu. Wszystkie wątki powinny czekać na bieżący wątek niezależnie od operacji (odczyt / zapis).
Prosty test wydajności dla ConcurrentHashMap vs Synchronized HashMap
. Przepływ testu wywołuje put
w jednym wątku i jednocześnie get
w trzech wątkach Map
. Jak powiedział @trshiv, ConcurrentHashMap ma wyższą przepustowość i prędkość, dla której operacja odczytu bez blokady. W rezultacie, gdy czasy operacji się 10^7
kończą, ConcurrentHashMap jest 2x
szybszy niż Synchronized HashMap.
SynchronizedMap
i ConcurrentHashMap
oba mają klasę bezpieczeństwa wątków i mogą być używane w aplikacjach wielowątkowych, główna różnica między nimi dotyczy sposobu, w jaki osiągają bezpieczeństwo wątków.
SynchronizedMap
uzyskuje blokadę na całej instancji Map, jednocześnie ConcurrentHashMap
dzieli instancję Map na wiele segmentów i blokuje je.
Zgodnie z dokumentacją java
Hashtable i Collections.synchronizedMap (new HashMap ()) są synchronizowane. Ale ConcurrentHashMap jest „współbieżna”.
Kolekcja współbieżna jest bezpieczna wątkowo, ale nie podlega pojedynczej blokadzie wykluczenia.
W szczególnym przypadku ConcurrentHashMap bezpiecznie zezwala na dowolną liczbę jednoczesnych odczytów, a także przestrajalną liczbę współbieżnych zapisów. Klasy „zsynchronizowane” mogą być przydatne, gdy trzeba uniemożliwić dostęp do kolekcji za pośrednictwem jednej blokady kosztem gorszej skalowalności.
W innych przypadkach, w których wiele wątków ma uzyskać dostęp do wspólnej kolekcji, zwykle preferowane są wersje „współbieżne”. Niezsynchronizowane kolekcje są preferowane, gdy kolekcje są niewspółdzielone lub są dostępne tylko wtedy, gdy przechowują inne blokady.
Hashtable
iSynchronized HashMap
?