блокировка под ключ, кроме блокировки всей карты в HashMap

1

У меня есть большая карта = 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)
Теги:
multithreading
concurrenthashmap
locking

1 ответ

2

в 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 заботится о возврате замков в том же порядке для того же набора ключей для блокировки, чтобы вы избежали проблем с философами столовой.

  • 0
    Спасибо @radai
  • 0
    Это означает, что никакие другие ключи put () / get () / compute () не заблокированы?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню