【问题标题】:Query regarding ConcurrentHashMap in JavaJava中关于ConcurrentHashMap的查询
【发布时间】:2013-09-05 09:35:01
【问题描述】:

我对@9​​87654321@有一个疑问。

ConcurrentHashMap 是并发访问的映射。 ConcurrentHashMap 实现 ConcurrentMap 扩展 Map

a) ConcurrentHashMap 实现了ConcurrentMap 中定义的原子方法(如putifAbsent 等)。

b) 但是,ConcurrentMap 扩展的 Map 接口中的方法呢? 它们现在是如何原子的?有没有被ConcurrentHashMap重新实现过

如果我有 ConcurrentHashMap 类型的引用并从 Map 接口(例如 put)或任何其他方法,该方法是原子方法吗?

【问题讨论】:

  • 查看代码你看到了什么?它看起来像复制还是重新实现?

标签: java map concurrency


【解决方案1】:

ConcurrentHashMap 不扩展 HashMap。它们都是hash table 的实现,但为了提供并发,ConcurrentHashMap 与 HashMap 有非常不同的内部结构。

如果您向接受 Map 的方法提供 ConcurrentHashMap,那么这将起作用,并且您将获得预期的并发行为。 Map 只是一个描述一组方法的接口,ConcurrentHashMap 以并发行为实现该接口。

“并发”和“原子”是有区别的。并发意味着多个操作可以同时发生,并且 Map(或我们正在谈论的任何数据结构)将始终处于有效状态。这意味着您可以有多个线程在此映射上调用 put()、get()、remove() 等,并且永远不会出现任何错误(如果您使用常规 HashMap 尝试此操作,您将收到错误,因为它不是旨在处理并发)。

Atomic 意味着采取多个步骤的操作似乎对其他线程采取了一个步骤 - 公平地说,他们知道它已经完全完成或者甚至还没有开始。对于 ConcurrentHashMap,putIfAbsent() 就是这样一个例子。来自 javadoc,

如果指定的键尚未与值关联,则将其与给定值关联。这相当于:

if (!map.containsKey(key)) {
   return map.put(key, value);
else
   return map.get(key);

除了动作是原子执行的。

如果您尝试使用 ConcurrentHashMap 执行上述代码,则不会出现任何错误(因为它是并发的),但有一个很好的变化是其他线程将与主线程交错,您的条目将被覆盖或删除. ConcurrentMap 指定原子的 putIfAbsent() 方法,以确保实现可以原子地执行这些步骤,而不受其他线程的干扰。

【讨论】:

    【解决方案2】:

    Map 只是一个接口。因此ConcurrentHashMap 具有这些方法的原子实现。

    putIfAbsent 方法是在并发环境中执行原子if not contains then put 的便捷方式,即使Map 实际上是ConcurrentHashMap 类型,您也无法从Map 接口执行此操作。

    【讨论】:

      【解决方案3】:

      put() 和 remove() 等这些方法的实现是在最终的 Sync 对象上获取锁,并发检索总是会给出地图上最新的数据。

      在对整个 Map 进行操作的 putAll() 或 clear() 的情况下,并发读取可能仅反映部分条目的插入和删除。

      以下两个链接将帮助您理解: http://javarevisited.blogspot.in/2013/02/concurrenthashmap-in-java-example-tutorial-working.html

      http://www.javamex.com/tutorials/synchronization_concurrency_8_hashmap2.shtml

      【讨论】:

      • 这完全取决于实现。您所说的对于 HashMap 是正确的(尽管内存可见性是您的问题中最少的问题,但您会得到错误),但对于 ConcurrentHashMap 则不然,所有更改都立即对其他线程可见。
      • @TomMcIntyre:可能是我不清楚,但从文档中它清楚地说声明“putAll 和 clear,并发检索可能仅反映插入或删除某些条目”。 docs.oracle.com/javase/7/docs/api/java/util/concurrent/…。如果您能帮助我进一步了解,那就太好了。
      • 我的评论更多是针对您的第一段。如果一个线程在 ConcurrentHashMap 上调用 put() 返回,所有其他线程将能够看到该操作的结果,不需要进一步同步。
      • @TomMcIntyre:感谢您的澄清。更正了我的回复。
      猜你喜欢
      • 1970-01-01
      • 2018-06-15
      • 2011-02-19
      • 2013-07-13
      • 2013-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多