【问题标题】:ConcurrentHashMap in Java locking mechanism for computeIfPresent用于computeIfPresent的Java锁定机制中的ConcurrentHashMap
【发布时间】:2017-06-14 10:58:05
【问题描述】:

我正在使用 Java 8,想知道 ConcurrentHashMapcomputeIfPresent 操作是否锁定了整个表/映射或只锁定了包含密钥的 bin。

来自computeIfPresent方法的documentation

其他线程在此映射上的某些尝试更新操作可能会在计算过程中被阻塞,因此计算应该简短而简单,并且不得尝试更新此映射的任何其他映射

当为一个键调用这个方法时,看起来整个地图都被锁定了。如果某个键的值被更新,为什么必须锁定整个地图?锁定包含键/值对的 bin 不是更好吗?

【问题讨论】:

  • 是的,根据我的解释,您也阻止了其他尝试调用此方法的线程。锁用于保护您的数据结构免受数据损坏和多个线程试图修改数据结构的不良影响。从文档中还说,此方法的作用是重新计算键及其关联值的新映射。这意味着这个操作可能会修改数据结构的各个部分(因为需要找到一个新的“桶”),这可能就是你需要锁定其他线程的原因。

标签: java multithreading java.util.concurrent concurrenthashmap


【解决方案1】:

从实现来看(Oracle JDK 1.8.0_101),只是对应的bin被锁定了。这与您引用的文档 sn-p 并不矛盾,因为它提到可能会阻止 一些 更新操作,而不一定是全部。当然,如果文档明确说明什么被锁定会更清楚,但这会将实现细节泄漏到接口的事实上的一部分。

【讨论】:

    【解决方案2】:

    如果您查看ConcurrentHashMap#computeIfPresent 的源代码,您会注意到同步是直接在节点本身上进行的。

    因此,只有当您尝试更新任何正在计算的节点时,操作才会阻塞。其他节点应该没有问题。

    据我了解,直接在节点上同步实际上是 ConcurrentHashMap 与旧 Hashtable 的主要附加组件。

    如果您查看哈希表的源代码,您会注意到同步范围要广泛得多。 相反ConcurrentHashMap 中的任何同步都直接发生在节点上。

    Hashtable documentation结尾也提示:

    [...] 哈希表已同步。如果线程安全的实现不是 需要时,建议使用 HashMap 代替 Hashtable。 如果一个 需要线程安全的高并发实现,那么它是 建议使用 ConcurrentHashMap 代替 Hashtable。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-07-18
      • 1970-01-01
      • 2021-07-30
      • 1970-01-01
      • 2017-02-06
      相关资源
      最近更新 更多