【问题标题】:Why get method in ConcurrentHashMap is blocking?为什么 ConcurrentHashMap 中的 get 方法被阻塞?
【发布时间】:2012-10-05 06:37:40
【问题描述】:

我对 Java 中的 ConcurrentHashMap 有疑问。它在内部调用 readValueUnderLock。为什么在获取操作的情况下需要锁定。在这种情况下,这个条件将是真的 (entry.value==null) 这会导致调用 readValueUnderLock)

【问题讨论】:

    标签: java locking concurrenthashmap


    【解决方案1】:

    来自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 修订版将填补空白以澄清这一点), 但是比尔·普格曾经建议我们无论如何都要把它放进去 为了保守的迂腐正确。 回想起来,我不太确定这是一个好主意,因为 它引导人们提出奇异的理论。

    【讨论】:

    • 但不确定如何使用其表分配重新排序 HashEntry 初始化,我想了解在哪个条件键不会为空而值可能为空,从 java doc 看来也是不知道永远不会发生,那么为什么他们包含这种锁定方法(因为 HashEntry 实际上是不可变的,所有字段都是最终的,除了可变的值)
    • @tarunk 从 javadoc 看来它是为特殊情况编写的。
    • 是的,任何关于这种特殊情况的想法,它是如何发生的,因为 jsr 133 保证了对 final/volatile 变量的排序。
    • 谢谢阿米特,但我仍然有一些疑问,因为构造函数中有一些初始化保证(通过确保在构造过程中不会被转义),在构造对象时没有其他线程可以读取对象.
    【解决方案2】:

    为了从哈希映射中读取值,代码必须首先找到该值。如果另一个线程在第一个线程查找该值时添加了一个值,则可能会使搜索脱轨。本质上,哈希映射可以执行以下操作:

    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
    

    如果这个列表是一个数组列表,而另一个线程需要调整它的大小,这对于遍历它的线程来说将是一个大问题。

    【讨论】:

      猜你喜欢
      • 2015-12-31
      • 2017-01-26
      • 2014-08-11
      • 1970-01-01
      • 1970-01-01
      • 2013-06-04
      • 2019-10-16
      • 2016-11-06
      • 2020-08-22
      相关资源
      最近更新 更多