Может ли concurrntHashMap одновременно гарантировать истинную безопасность потоков и параллелизм? - PullRequest
3 голосов
/ 15 июня 2011

Мы знаем, что ConcurrentHashMap может обеспечить одновременный доступ к нескольким потокам для повышения производительности, и внутри этого класса сегменты синхронизируются (я прав?). Вопрос в том, может ли эта конструкция гарантировать безопасность резьбы? Скажем, у нас есть более 30 потоков, которые получают доступ и изменяют объект, отображаемый одним и тем же ключом в экземпляре ConcurrentHashMap, я полагаю, им все равно придется выстраиваться для этого, не так ли?

Из моего воспоминания о том, что в книге "Параллелизм Java на практике" говорится, что ConcurrentHashMap обеспечивает одновременное чтение и достойный уровень одновременной записи. в вышеупомянутом сценарии, и если мои предположения верны, производительность не будет лучше, чем при использовании API-интерфейса статической синхронизации Коллекции api?

Спасибо за разъяснения, John

Ответы [ 5 ]

6 голосов
/ 15 июня 2011

Вам все равно придется синхронизировать любой доступ к изменяемому объекту, и, поскольку вы подозреваете, что у любого доступа к одному и тому же ключу все равно будет конфликт.Повышение производительности обеспечивается за счет доступа к различным клавишам, что, конечно, является более типичным случаем.

2 голосов
/ 15 июня 2011

Вопрос в том, может ли эта конструкция гарантировать безопасность резьбы?

Гарантирует поточную безопасность карты; то есть, что доступ и обновления на карте имеют четко определенное и упорядоченное поведение при наличии нескольких потоков, выполняющих обновления одновременно.

Это гарантирует потокобезопасность ключа или объектов значения. И это не обеспечивает никакой формы синхронизации более высокого уровня.

Скажем, у нас более 30 потоков, которые получают доступ и изменяют объект, отображаемый одним и тем же ключом в экземпляре ConcurrentHashMap, я полагаю, что они все еще должны выстроиться в линию, не так ли?

Если у вас несколько потоков, пытающихся использовать один и тот же ключ, то их операции неизбежно будут до некоторой степени сериализованы. Это неизбежно.

На самом деле, если кратко взглянуть на исходный код, то похоже, что ConcurrentHashMap возвращается к использованию обычных блокировок, если слишком много конфликтов для конкретного сегмента карты. И если у вас есть несколько потоков, пытающихся получить доступ и обновить один и тот же ключ одновременно, это вызовет блокировку.

2 голосов
/ 15 июня 2011

Все, что ConcurrentMap может дать вам параллелизм, заключается в том, что изменения самой карты выполняются атомарно, и что любые записи происходят до любых чтений (это важно, поскольку обеспечивает безопасную публикацию любая ссылка с карты.

Безопасная публикация означает, что любой (изменяемый) объект, извлеченный из карты, будет виден со всеми записями в него до того, как было размещено на карте. Это не поможет опубликовать изменения, сделанные после его получения.

Однако параллелизм и безопасность потоков обычно сложно рассуждать и исправлять, если у вас есть изменяемые объекты, которые изменяются несколькими сторонами. Обычно вы должны заблокировать, чтобы сделать это правильно Лучшим подходом часто является использование неизменяемых объектов в сочетании с условными методами ConcurrentMap putIfAbsent / replace и линеаризация вашего алгоритма таким образом. Этот стиль без блокировки имеет тенденцию быть более легким для рассуждения.

1 голос
/ 15 июня 2011

сначала помните, что поточно-ориентированный инструмент не гарантирует поточно-безопасное использование самого по себе

конструкция if(!map.contains(k))map.put(k,v); для putIfAbsent, например, не является поточно-ориентированной

и каждое значение доступа / модификации все еще должно быть независимо от потока безопасности

0 голосов
/ 15 июня 2011

Чтения происходят одновременно даже для одного и того же ключа, поэтому производительность будет выше для типичных приложений.

...