ComputeiPresent Java锁定机制中的ConcurrentHashMap

ComputeiPresent Java锁定机制中的ConcurrentHashMap,java,multithreading,java.util.concurrent,concurrenthashmap,Java,Multithreading,Java.util.concurrent,Concurrenthashmap,我使用的是Java 8,我想知道ConcurrentHashMap的computeIfPresent操作是否锁定了整个表/映射,或者只锁定了包含键的bin 从computeIfPresent方法的 在计算过程中,其他线程在此映射上尝试的某些更新操作可能会被阻止,因此计算应该简短,并且不得尝试更新此映射的任何其他映射 这看起来像是在为密钥调用此方法时锁定了整个映射。如果某个键的值被更新,为什么必须锁定整个地图?锁定包含键/值对的bin不是更好吗 根据实现(Oracle JDK 1.8.0_101)

我使用的是Java 8,我想知道
ConcurrentHashMap
computeIfPresent
操作是否锁定了整个表/映射,或者只锁定了包含键的bin

computeIfPresent
方法的

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


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

根据实现(Oracle JDK 1.8.0_101)判断,只有相应的bin被锁定。这与您引用的文档片段并不矛盾,因为它提到了一些更新操作可能会被阻止,而不一定是全部。当然,如果文档明确说明了什么被锁定,就会更清楚,但这会将实现细节泄露到接口的实际部分。

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

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

据我所知,直接在节点上进行同步实际上是
ConcurrentHashMap
与旧
Hashtable
的主要附加功能


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

报告最后还建议:

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


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