【发布时间】:2012-10-05 06:37:40
【问题描述】:
我对 Java 中的 ConcurrentHashMap 有疑问。它在内部调用 readValueUnderLock。为什么在获取操作的情况下需要锁定。在这种情况下,这个条件将是真的 (entry.value==null) 这会导致调用 readValueUnderLock)
【问题讨论】:
标签: java locking concurrenthashmap
我对 Java 中的 ConcurrentHashMap 有疑问。它在内部调用 readValueUnderLock。为什么在获取操作的情况下需要锁定。在这种情况下,这个条件将是真的 (entry.value==null) 这会导致调用 readValueUnderLock)
【问题讨论】:
标签: java locking concurrenthashmap
来自readValueUnderLock的源码java doc注释
/**
* Reads value field of an entry under lock. Called if value
* field ever appears to be null. This is possible only if a
* compiler happens to reorder a HashEntry initialization with
* its table assignment, which is legal under memory model
* but is not known to ever occur.
*/
来自link
不完全是。你是对的,它永远不应该被调用。 然而,JLS/JMM 可以被解读为不是绝对的 禁止因为弱点而被调用 在决赛之间的要求排序关系 vs volatiles 在构造函数中设置(键是最终的,值是 volatile),使用线程读取 入口对象。 (在 JMM-ese 中,排序约束为 决赛落在 synchronizes-with 关系之外。) 这就是文档评论(粘贴在下面)所指的问题。 没有人想到任何实际漏洞 处理器/编译器可能会发现产生空值读取, 并且可以证明不存在(也许有一天 JLS/JMM 修订版将填补空白以澄清这一点), 但是比尔·普格曾经建议我们无论如何都要把它放进去 为了保守的迂腐正确。 回想起来,我不太确定这是一个好主意,因为 它引导人们提出奇异的理论。
【讨论】:
为了从哈希映射中读取值,代码必须首先找到该值。如果另一个线程在第一个线程查找该值时添加了一个值,则可能会使搜索脱轨。本质上,哈希映射可以执行以下操作:
calculate hash
go to location hash in the array
look to see if there's a list
iterate through the list until value is found
如果这个列表是一个数组列表,而另一个线程需要调整它的大小,这对于遍历它的线程来说将是一个大问题。
【讨论】: