Яка різниця між використанням класу обгортки SynchronizedMap
, на а HashMap
та ConcurrentHashMap
?
Це просто можливість змінити HashMap
час ітерації ( ConcurrentHashMap
)?
Яка різниця між використанням класу обгортки SynchronizedMap
, на а HashMap
та ConcurrentHashMap
?
Це просто можливість змінити HashMap
час ітерації ( ConcurrentHashMap
)?
Відповіді:
Синхронізовано HashMap
:
Кожен метод синхронізується за допомогою блокування об'єктного рівня. Тож способи отримати і поставити на синхронізують придбання блокування.
Блокування всієї колекції - це продуктивні витрати. Хоча одна нитка тримається за замок, жодна інша нитка не може використовувати колекцію.
ConcurrentHashMap
була представлена в JDK 5.
Немає блокування на рівні об'єкта, блокування є набагато тоншою деталізацією. Для a ConcurrentHashMap
, блоки можуть знаходитися на рівні відра хешмапу.
Ефект блокування нижнього рівня полягає в тому, що ви можете мати одночасних читачів і записувачів, що неможливо для синхронізованих колекцій. Це призводить до набагато більшої масштабованості.
ConcurrentHashMap
не кидає a, ConcurrentModificationException
якщо один потік намагається змінити його, тоді як інший повторюється над ним.
Ця стаття Java 7: HashMap проти ConcurrentHashMap - це дуже добре прочитане. Настійно рекомендується.
ConcurrentHashMap
«S size()
результат може втратити свою актуальність. size()
дозволяється повернути апроксимацію замість точного підрахунку відповідно до книги "Конкурс Java в практиці". Тож цей метод слід застосовувати обережно.
Коротка відповідь:
Обидві карти є безпечними потоками реалізації Map
інтерфейсу. ConcurrentHashMap
реалізується для підвищення пропускної здатності у випадках, коли очікується висока одночасність.
Стаття Брайана Геца про ідею, що ConcurrentHashMap
стоїть, дуже добре прочитана. Настійно рекомендується.
Map m = Collections.synchronizedMap(new HashMap(...));
docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
ConcurrentHashMap
безпечно для потоків без синхронізації всієї карти. Читання може відбуватися дуже швидко, поки запис робиться за допомогою блокування.
Ми можемо досягти безпеки потоку, використовуючи як ConcurrentHashMap, так і синхронізовану Hashmap. Але різниці є дуже багато, якщо подивитися на їх архітектуру.
Він буде підтримувати замок на рівні об'єкта. Отже, якщо ви хочете виконати будь-яку операцію, наприклад, поставити / дістати, то спочатку потрібно придбати замок. У той же час, інші потоки не дозволяють виконувати жодну операцію. Тож одночасно над цим може працювати лише одна нитка. Тож час очікування тут збільшиться. Можна сказати, що продуктивність порівняно низька, якщо ви порівнюєте з ConcurrentHashMap.
Він підтримуватиме блокування на рівні сегмента. Він має 16 сегментів і підтримує рівень сумісності як 16 за замовчуванням. Тож одночасно на ConcurrentHashMap можна працювати 16 потоків. Більше того, операція читання не потребує блокування. Таким чином, будь-яка кількість потоків може виконати операцію get на ньому.
Якщо нитка1 хоче виконати операцію поставлення в сегменті 2, а нитка2 хоче виконати операцію поставлення на сегменті 4, то це дозволено тут. Значить, 16 потоків можуть одночасно виконувати операцію оновлення (поставити / видалити) на ConcurrentHashMap.
Так що часу очікування тут буде менше. Отже, продуктивність порівняно краща за синхронізовану Hashmap.
Обидві є синхронізованою версією HashMap з різницею в їх основній функціональності та внутрішній структурі.
ConcurrentHashMap складається з внутрішніх сегментів, які концептуально можуть розглядатися як незалежні HashMaps. Усі такі сегменти можуть бути заблоковані окремими потоками у високих паралельних виконаннях. Таким чином, кілька потоків можуть отримати / поставити пари ключових значень з ConcurrentHashMap, не блокуючи / чекаючи один одного. Це реалізовано для підвищення пропускної здатності.
тоді як
Collections.synchronizedMap () , ми отримуємо синхронізовану версію HashMap і доступ до неї блокується. Це означає, що якщо кілька потоків намагаються одночасно отримати доступ до sinkronizedMap, їм буде дозволено синхронізовано отримувати / ставити пари ключових значень.
ConcurrentHashMap
використовує тонкозернистий механізм блокування, відомий як такий, lock stripping
що дозволяє отримати більший ступінь спільного доступу. Завдяки цьому він забезпечує кращу одночасність та масштабованість .
Крім того, ітератори, для ConcurrentHashMap
яких повернулися, є досить послідовними, замість того, щоб не швидко проходити техніка, що використовується синхронізованим HashMap.
Методи SynchronizedMap
утримування блокування на об'єкті, тоді як в ConcurrentHashMap
ньому існує концепція "блокування смуг", де замість них тримаються відра з вмістом. Таким чином покращилася масштабованість та продуктивність.
ConcurrentHashMap:
1) Обидві карти є безпечними для потоків реалізаціями інтерфейсу Map.
2) ConcurrentHashMap реалізується для підвищення пропускної здатності в тих випадках, коли очікується висока конкурентоспроможність.
3) Немає блокування на рівні об'єкта.
Синхронізована хеш-карта:
1) Кожен метод синхронізується за допомогою блокування об'єктного рівня.
ConcurrentHashMap дозволяє одночасно мати доступ до даних. Вся карта поділена на сегменти.
Операція читання, тобто. get(Object key)
не синхронізується навіть на рівні сегмента.
Але операції запису, тобто. remove(Object key), get(Object key)
придбати замок на рівні сегмента. Заблокована лише частина всієї карти, інші потоки все ще можуть читати значення з різних сегментів, крім заблокованої.
SynchronizedMap, з іншого боку, набувають блокування на рівні об'єкта. Усі потоки повинні чекати поточного потоку незалежно від роботи (читання / запис).
Простий тест продуктивності для ConcurrentHashMap проти синхронізованого HashMap
. Тестовий потік викликає put
один потік і одночасно викликає get
три потоки Map
. Як сказав @trshiv, ConcurrentHashMap має більш високу пропускну здатність і швидкість, для читання яких працює без блокування. Результат - коли час роботи закінчується 10^7
, ConcurrentHashMap 2x
швидше, ніж синхронізований HashMap.
SynchronizedMap
і ConcurrentHashMap
вони є безпечним для ниток класу, і їх можна використовувати в багатопотокових програмах, головна відмінність між ними полягає в тому, як вони досягають безпеки потоку.
SynchronizedMap
отримує блокування всього екземпляра Map, тоді як ConcurrentHashMap
розділяє екземпляр Map на кілька сегментів і блокування робиться на них.
Відповідно до java doc
Hashtable і Collections.synchronizedMap (новий HashMap ()) синхронізуються. Але ConcurrentHashMap є "одночасним".
Паралельна колекція є безпечною для потоків, але не регулюється одним блокуванням виключення.
У конкретному випадку ConcurrentHashMap, він безпечно дозволяє будь-яку кількість одночасних зчитувань, а також регульовану кількість одночасних записів. "Синхронізовані" класи можуть бути корисні, коли вам потрібно запобігти доступ до колекції за допомогою одного блокування за рахунок біднішої масштабованості.
В інших випадках, коли очікується, що декілька потоків мають доступ до загальної колекції, зазвичай є "одночасними" версіями. І несинхронізовані колекції є кращими, коли будь-які колекції не мають спільного доступу, або доступні лише тоді, коли зберігаються інші блоки.
Hashtable
іSynchronized HashMap
?