ConcurrentHashMap 不扩展 HashMap。它们都是哈希表的实现,但是为了提供并发性,ConcurrentHashMap 与 HashMap 有非常不同的内部结构。
如果您向接受 Map 的方法提供 ConcurrentHashMap,那么这将起作用,并且您将获得预期的并发行为。Map 只是一个描述一组方法的接口,ConcurrentHashMap 以并发行为实现该接口。
“并发”和“原子”之间是有区别的。并发意味着多个操作可以同时发生,并且 Map(或我们正在谈论的任何数据结构)将始终处于有效状态。这意味着您可以有多个线程在此映射上调用 put()、get()、remove() 等,并且永远不会出现任何错误(如果您使用常规 HashMap 尝试此操作,您将收到错误,因为它不是旨在处理并发)。
原子意味着一个采取多个步骤的动作似乎对其他线程采取了一个步骤——公平地因为他们知道它已经完全完成或者甚至还没有开始。对于 ConcurrentHashMap,putIfAbsent() 就是这样一个例子。从javadoc,
如果指定的键尚未与值关联,则将其与给定值关联。这相当于:
if (!map.containsKey(key)) {
return map.put(key, value);
else
return map.get(key);
除了动作是原子执行的。
如果您尝试使用 ConcurrentHashMap 执行上述代码,则不会出现任何错误(因为它是并发的),但有一个很好的变化是其他线程将与主线程交错并且您的条目将被覆盖或删除。ConcurrentMap 指定原子 putIfAbsent() 方法以确保实现可以原子地执行这些步骤,而不受其他线程的干扰。