Java 中的 ConcurrentHashMap 用于 computeIfPresent 的锁定机制

ConcurrentHashMap in Java locking mechanism for computeIfPresent

我正在使用 Java 8,想知道 ConcurrentHashMapcomputeIfPresent 操作是否锁定了整个 table/map 或仅包含包含钥匙。

来自computeIfPresent方法的documentation

Some attempted update operations on this map by other threads may be blocked while computation is in progress, so the computation should be short and simple, and must not attempt to update any other mappings of this map

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

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

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

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

根据我的理解,直接在节点上同步实际上是 ConcurrentHashMap 与旧 Hashtable 的主要 add-on。

如果您查看散列表的源代码,您会发现同步范围更广。 相反ConcurrentHashMap 中的任何同步都直接发生在节点上。

结尾Hashtable documentation还提示:

[...] Hashtable is synchronized. If a thread-safe implementation is not needed, it is recommended to use HashMap in place of Hashtable. If a thread-safe highly-concurrent implementation is desired, then it is recommended to use ConcurrentHashMap in place of Hashtable.