У меня есть большая карта = ConcurrentHashMap() в Java, а Key, Value - это некоторая структура объекта. Предположим, что набор ключей этой карты - keySet.
Теперь у меня есть процедура расчета ниже. Мой вопрос в том, как я могу получить лучшую производительность, не используя целую блокировку карты. Существуют ли такие опции, как использование блокировки с помощью одной клавиши или использование каких-либо других структур данных?
Учитывая, что это большая карта, использование блокировки с каждой клавишей может быть неприемлемым.
multiThread(): for(0 to N): K = subset(keySet, m) where m is much smaller than keySet.size lock(map) for(key in K): result = func1(map.get(key), result) for(key in K): map.put(key, func2(map.get(key), result)) releaseLock(map)
в java 8+ ConcurrentHashMap как функция compute(), которая позволяет выполнять операцию атомарного чтения-изменения-записи на одном ключе, так что вы можете сделать что-то вроде:
map.compute(key, () -> {
//call func2 to compute new value and return it
});
если, однако, вы хотите, чтобы атомарное чтение-изменение-запись для всего набора ключей (так что вы перебираете свой набор ключей для вычисления результата, а затем меняете все эти ключи с использованием этого предварительно вычисленного результата), тогда в ConcurrentHashMap нет средства для обеспечения этой блокировки.
однако вы можете использовать guava Striped lock, например:
Striped<Lock> arrayOfLocks = Striped.lock(20);
// ...later on...
K = subset(keySet, m);
Iterable<Lock> toObtain = arrayOfLocks.bulkGet(K);
for (Lock l : toObtain) { lock it }
try {
//do your modifications - your holding the stripe locks for all the keys
} finally {
for (Lock l : toObtain) { unlock it }
}
lock striping - это концепция назначения блокировок для разных "областей" структуры данных - здесь это делается с помощью hashCode ваших ключей.
вам нужно очень тщательно выбирать размер блокировки, чтобы сбалансировать слишком много полос (где вы заблокируете всю карту и сделаете ее медленнее, чем один глобальный замок) и слишком много полос (где вы будете захватывать много замков, в зависимости от размера K).
Striped заботится о возврате замков в том же порядке для того же набора ключей для блокировки, чтобы вы избежали проблем с философами столовой.