首次引入ConcurrentMap
界面时,它提供了一些额外的"复杂的"这样可以使一些常见的多步骤动作成为原子。
然而,Map
接口似乎吸收了ConcurrentMap
中与Java 8中一样的所有这类方法。
现在Java中ConcurrentMap
接口的意义和用途是什么?
答案 0 :(得分:2)
ConcurrentMap 保证同步或原子性:
提供线程安全性和原子性保证的映射。
Map 不保证同步或原子性
默认实现不保证此方法的同步或原子性属性。
此外,您可以检查并查看默认方法不同(如merge
)。
答案 1 :(得分:1)
正如@user7294900共享的文档中所述,de
为其实现中的同步或原子性提供了保证。例如,方法ConcurrentMap
在两个接口中实现如下:
<强> Map.java 强>
forEach
ConcurrentMap.java
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch(IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
虽然前者在对Map的修改中抛出了一个例外,它无法再访问该条目,后者将继续迭代其余可用条目。
答案 2 :(得分:0)
ConcurrentMap表示支持并发访问并保证原子性的Map,即您可以从不同的线程获取和放置值,而不会有损害数据完整性的风险。特别是,它提供了原子putIfAbsent
,remove
和replace
方法。这是什么意思?
想象一下,你有一个程序,有两个线程访问一个地图。线程1同时调用map.putIfAbsent("name", "Mike")
和线程2调用map.putIfAbsent("name", "John")
。 putIfAbsent
应该返回已经存在的值,或者放入新值并返回null。它就像
if (!map.containsKey(key))
return map.put(key, value);
else
return map.get(key);
但是,如果,在执行第一行(并且条件为真)之后,线程1暂停,那么线程2可以运行?线程2将在程序返回到线程1之前将其值放在地图中,线程1仍然认为地图没有名称值。因此,当它执行第2行时,它会设置其值,但不会按预期返回null,而是返回值第2次设置,这不应该发生。
这称为竞争条件,因为putIfAbsent的执行在线程1中被中断(即putIfAbsent是非原子的)。但是使用ConcurrentMap,这些方法是原子的,不能相互中断,从而消除了这些问题。