>?,java,concurrency,race-condition,java.util.concurrent,concurrenthashmap"/>

首页 > 解决方案 > 如何从 ConcurrentHashMap 中删除用作值的 Set>?

问题描述

让我们考虑以下代码:

ConcurrentHashMap<String, Set<String>> map = new ConcurrentHashMap<>();

// Add element: {mapKey, setValue}

map.computeIfAbsent(mapKey, new Function<String, Set<String>>() {
    @Override
    public Set<String> apply(String mapK) {
        return ConcurrentHashMap.newKeySet();
    }
}).add(setValue);

// Remove element: {mapKey, setValue}

Set<String> updatedSet = map.computeIfPresent(mapKey, new BiFunction<String, Set<String>, Set<String>>() {
    @Override
    public Set<String> apply(String mapK, Set<String> old) {
        old.remove(setValue);
        return old;
    }
});

// I need remove mapKey, but I cannod do this like this, because of race condition bug
if (updatedSet.isEmpty()) {
    map.remove(mapKey);
}

所以,我们可以看到:

  1. 我们有ConcurrentHashMap<String, Set<String>>地图,key地图的位置是String,并且valueConcurrentHashSet
  2. 我需要删除set, 这是map, when setis的值empty
  3. set由于竞争条件错误,我无法实现天真的删除。

我的问题有什么绝妙的解决方案吗?

标签: javaconcurrencyrace-conditionjava.util.concurrentconcurrenthashmap

解决方案


computeIfPresent如果映射器返回,则删除条目nullnull如果要删除条目,请从映射器返回,而不是在单独的步骤中执行删除。

(此外,您应该真正将 折叠.add(setValue)到您的computeIfAbsent映射器中,并使用compute而不是computeIfAbsent,因为您现在没有做任何事情来保护add呼叫。使用merge也是一种选择。)


推荐阅读