ConcurrentHashMap和跨越2个单独调用的操作

时间:2019-05-06 22:56:36

标签: java concurrency concurrenthashmap

我了解ConcurrentHashMap方法是线程安全的,但是例如不是原子的复合操作呢?请看这段代码-如果两个不同的线程使用相同的“ myKey”同时调用它,则不可能比赛条件会发生吗?

myMap是一个ConcurrentHashMap

myValues = myMap.get(myKey);
if (myValues == null) {
    myValues = new List()
    myMap.add(myKey, myValues);
}
myValue.add(new list item);

我如何仅使用ConcurrentHashMap以线程安全的方式编写以上代码,而又不使用单独的Locks等,

putIfAbsent似乎无法解决该问题,或者像这样可行:

myValues =  myMap.putIfAbsent(myKey, new List());
myValues.add(new list item);

这对线程安全吗?
谢谢

1 个答案:

答案 0 :(得分:2)

使用原子的computeIfAbsent

文档:

  

如果指定的键尚未与值关联,则尝试   使用给定的映射函数计算其值并输入   进入此地图,除非为null。整个方法调用均已执行   从原子上讲,因此每个键最多只能应用一次该功能。一些   其他线程在此地图上尝试的更新操作可能是   在计算进行过程中被阻塞,因此计算应   简短而简单,不得尝试更新以下内容的任何其他映射   这张地图。

简单用法:

ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<>();
List<String> list = map.computeIfAbsent("myKey", key -> new CopyOnWriteArrayList<>());

修改
正如@Holger正确注意到的那样,在这种情况下使用ArrayList是不安全的。使用CopyOnWriteArrayList(这是ArrayList的线程安全变体)要安全得多。