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

时间:2017-01-29 00:22:22

标签: java multithreading java.util.concurrent concurrenthashmap

我正在使用Java 8,并且想知道AngularJS的{​​{1}}操作是否确实锁定了整个表/地图,或者只是锁定了包含密钥的bin。

来自type:"E"方法的documentation

  

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

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

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:1)

如果查看ConcurrentHashMap#computeIfPresent的源代码,您会注意到同步是直接在节点本身上进行的。 因此,只有在尝试更新正在计算的任何节点时,操作才会阻止。您不应该对其他节点有任何问题。 根据我的理解,直接在节点上的同步实际上是ConcurrentHashMap与旧Hashtable的主要附件。 如果你看一下哈希表的源代码,你会发现同步更广泛。相反,ConcurrentHashMap中的任何同步都直接在节点上发生。 Hashtable文档的结尾还表明:   [...] Hashtable已同步。如果没有线程安全的实现   需要时,建议使用HashMap代替Hashtable。如果一个   需要线程安全的高度并发实现,然后是   建议使用ConcurrentHashMap代替Hashtable。