我使用的是Java 8,并且想知道ConcurrentHashMap
的ConcurrentHashMap
操作是否锁定了整个表/映射,还是只锁定了包含密钥的bin。
来自文档的computeIfPresent
方法:
在计算过程中,可能会阻止其他线程在此地图上的一些尝试更新操作,因此计算应该简短且简单,并且不能试图更新此映射的任何其他映射。
这看起来整个映射在为密钥调用此方法时被锁定。如果某个键的值被更新,为什么整个映射必须被锁定?仅仅锁定包含密钥/值对的bin不是更好吗?
发布于 2017-01-29 00:58:12
从实现(Oracle 1.8.0_101)判断,只锁定了相应的bin。这与您引用的文档片段并不矛盾,因为它提到了一些更新操作可能会被阻止,而不一定是全部。当然,如果文档明确地说明了什么会被锁定,这会更清楚,但这会将实现细节泄露给接口的一个事实上的部分。
发布于 2017-01-29 01:14:31
如果您查看ConcurrentHashMap#computeIfPresent
的源代码,您会发现同步是直接在节点本身上进行的。
因此,只有在尝试更新正在计算的任何节点时,操作才会阻塞。您不应该对其他节点有任何问题。
据我所知,直接在节点上同步实际上是ConcurrentHashMap
与旧Hashtable
的主要附加部分。
如果您查看哈希表的源代码,您会注意到同步的范围要大得多。相反,ConcurrentHashMap
中的任何同步都直接发生在节点上。
Hashtable文档的结束还表明:
.哈希表是同步如果不需要线程安全实现,建议使用HashMap代替Hashtable。如果需要线程安全的高度并发实现,则建议使用ConcurrentHashMap代替Hashtable。
https://stackoverflow.com/questions/41916368
复制相似问题