我了解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);
这对线程安全吗?
谢谢
答案 0 :(得分:2)
使用原子的computeIfAbsent:
文档:
如果指定的键尚未与值关联,则尝试 使用给定的映射函数计算其值并输入 进入此地图,除非为null。整个方法调用均已执行 从原子上讲,因此每个键最多只能应用一次该功能。一些 其他线程在此地图上尝试的更新操作可能是 在计算进行过程中被阻塞,因此计算应 简短而简单,不得尝试更新以下内容的任何其他映射 这张地图。
简单用法:
ConcurrentHashMap<String, List<String>> map = new ConcurrentHashMap<>();
List<String> list = map.computeIfAbsent("myKey", key -> new CopyOnWriteArrayList<>());
修改
正如@Holger正确注意到的那样,在这种情况下使用ArrayList
是不安全的。使用CopyOnWriteArrayList(这是ArrayList
的线程安全变体)要安全得多。