В чем разница между использованием класса-оболочки SynchronizedMap
в HashMap
и ConcurrentHashMap
?
Это просто возможность изменить HashMap
во время его итерации (ConcurrentHashMap
)?
В чем разница между использованием класса-оболочки SynchronizedMap
в HashMap
и ConcurrentHashMap
?
Это просто возможность изменить HashMap
во время его итерации (ConcurrentHashMap
)?
Синхронизированный HashMap
:
Каждый метод синхронизируется с использованием блокировки уровня объекта. Таким образом, методы get и put на synchMap приобретают блокировку.
Блокировка всей коллекции - это накладные расходы. Хотя один поток держится за блокировку, ни один другой поток не может использовать коллекцию.
ConcurrentHashMap
был введен в JDK 5.
На уровне объекта нет блокировки. Блокировка имеет гораздо более мелкую детализацию. Для ConcurrentHashMap
блокировки могут быть на уровне хэш-карты.
Эффект блокировки нижнего уровня заключается в том, что у вас могут быть одновременно читатели и писатели, что невозможно для синхронизированных коллекций. Это приводит к гораздо большей масштабируемости.
ConcurrentHashMap
не бросает ConcurrentModificationException
, если один поток пытается изменить его, а другой выполняет итерацию по нему.
Эта статья Java 7: HashMap против ConcurrentHashMap - очень хорошее чтение. Очень рекомендуется.
Короткий ответ:
Обе карты являются потокобезопасными реализациями интерфейса Map
. ConcurrentHashMap
реализуется для большей пропускной способности в случаях, когда ожидается высокий concurrency.
Brian Goetz статья об идее ConcurrentHashMap
- очень хорошее чтение. Очень рекомендуется.
ConcurrentHashMap
является потокобезопасным без синхронизации всей карты. Считывание может происходить очень быстро, в то время как запись выполняется с помощью блокировки.
Мы можем обеспечить безопасность потоков, используя как ConcurrentHashMap, так и synchronizedHashmap. Но есть большая разница, если вы посмотрите на их архитектуру.
Он будет поддерживать блокировку на уровне объекта. Поэтому, если вы хотите выполнить какую-либо операцию, например put/get, вам сначала нужно приобрести блокировку. В то же время другим потокам не разрешается выполнять какую-либо операцию. Поэтому в то время на этом может работать только один поток. Таким образом, время ожидания будет увеличиваться здесь. Мы можем сказать, что производительность относительно низкая, если сравнивать с ConcurrentHashMap.
Он будет поддерживать блокировку на уровне сегмента. Он имеет 16 сегментов и поддерживает уровень concurrency как 16 по умолчанию. Таким образом, 16 потоков могут работать на ConcurrentHashMap. Более того, операция чтения не требует блокировки. Поэтому любое количество потоков может выполнять операцию get на нем.
Если thread1 хочет выполнить операцию ввода в сегменте 2, а thread2 хочет выполнить операцию put на сегменте 4, то это разрешено здесь. Средства, 16 потоков могут выполнять операцию обновления (put/delete) на ConcurrentHashMap за раз.
Итак, время ожидания здесь будет меньше. Следовательно, производительность относительно лучше, чем синхронизированнаяHashmap.
Оба являются синхронизированной версией HashMap с разницей в их основной функциональности и их внутренней структуре.
ConcurrentHashMap состоит из внутренних сегментов, которые можно рассматривать как независимые HashMaps концептуально. Все такие сегменты могут быть заблокированы отдельными потоками при высоких одновременных исполнениях. Таким образом, несколько потоков могут получить/поставить пары ключ-значение из ConcurrentHashMap без блокировки/ожидания друг друга. Это реализовано для большей пропускной способности.
тогда
Collections.synchronizedMap(), мы получаем синхронизированную версию HashMap и к ней обращаются блокируемо. Это означает, что если несколько потоков попытаются получить доступ к synchronizedMap в одно и то же время, им будет разрешено вводить пары "ключ-значение" по одному за раз синхронно.
ConcurrentHashMap
использует более мелкозернистый механизм блокировки, известный как lock stripping
, чтобы обеспечить большую степень совместного доступа. Благодаря этому он обеспечивает лучшую concurrency и масштабируемость.
Итераторы, возвращенные для ConcurrentHashMap
, являются слабо согласованными вместо fail fast technique, используемого Synchronized HashMap.
Способы SynchronizedMap
удерживают блокировку объекта, тогда как в ConcurrentHashMap
существует концепция "блокировки", где блокировки удерживаются на ведрах содержимого. Таким образом, улучшена масштабируемость и производительность.
ConcurrentHashMap:
1) Обе карты являются потокобезопасными реализациями интерфейса карты.
2) ConcurrentHashMap реализуется для большей пропускной способности в случаях, когда ожидается высокий concurrency.
3) В объекте нет блокировки.
Синхронизированная хэш-карта:
1) Каждый метод синхронизируется с использованием блокировки уровня объекта.
Простой тест производительности для ConcurrentHashMap против синхронизированного HashMap
. Тестовый поток вызывает put
в одном потоке и одновременно вызывает get
в трех потоках в Map
. Как сказал @trshiv, ConcurrentHashMap имеет более высокую пропускную способность и скорость для операций чтения без блокировки. В результате, когда время работы превышает 10^7
, ConcurrentHashMap работает 2x
быстрее, чем Synchronized HashMap.
ConcurrentHashMap позволяет одновременный доступ к данным. Вся карта разделена на сегменты.
Операция чтения, т.е. get(Object key)
не синхронизируется даже на уровне сегмента.
Но операции записи, т.е. remove(Object key), get(Object key)
получить блокировку на уровне сегмента. Только часть всей карты заблокирована, другие потоки по-прежнему могут считывать значения из разных сегментов, кроме заблокированных.
SynchronizedMap, с другой стороны, получить блокировку на уровне объекта. Все потоки должны ждать текущего потока независимо от работы (чтение/запись).
Согласно документу Java,
Hashtable и Collections.synchronizedMap (новый HashMap()) являются синхронизированы. Но ConcurrentHashMap является "одновременным".
Параллельная коллекция является поточно-ориентированной, но не управляется одной блокировкой исключения.
В конкретном случае ConcurrentHashMap это безопасно разрешает любое количество одновременных чтений, а также настраиваемое количество одновременно пишет. "Синхронизированные" классы могут быть полезны, когда вам нужно чтобы предотвратить любой доступ к коллекции через один замок, на за счет худшей масштабируемости.
В других случаях, когда несколько ожидается, что потоки получат доступ к общей коллекции "одновременный" версии обычно предпочтительнее. И несинхронизированные коллекции предпочтительнее, когда коллекции не являются общими или доступны только при удерживании других замков.