gpt4 book ai didi

java - 在数据竞争期间,线程能否读取 volatile 变量的初始空值?特别是在构造函数中为其分配了非空值时?

转载 作者:搜寻专家 更新时间:2023-11-01 03:13:46 25 4
gpt4 key购买 nike

  • 让我困惑的是这个。

ConcurrentHashMap中HashEntry的Java文档(jdk1.6.0_16)

...因为值字段是易变的,而不是最终的,对于非同步读取器来说,在通过数据竞争读取时看到空值而不是初始值是合法的 Java 内存模型。尽管导致这种情况的重新排序不太可能真正发生,但 Segment.readValueUnderLock 方法用作备份,以防在非同步访问方法中出现空(预初始化)值。

  • 这里是ConcurrentHashMap#Segment的get方法的实现


    V get(Object key, int hash) {
    if (count != 0) { // read-volatile
    HashEntry e = getFirst(hash);
    while (e != null) {
    if (e.hash == hash && key.equals(e.key)) {
    V v = e.value;
    if (v != null)
    return v;
    return readValueUnderLock(e); // recheck
    }
    e = e.next;
    }
    }
    return null;
    }
  • 和readValueUnderLock


V readValueUnderLock(HashEntry e) {
lock();
try {
return e.value;
} finally {
unlock();
}
}
  • 根据我的阅读和理解,每个线程都会读取 volatile 变量的最新值。

  • 那么线程什么时候读取初始空值呢?特别是在构造函数完成之前分配值的 HashEntry 中。 (另请注意,HashEntry 的引用永远不会逃脱其构造函数。)

  • 我很困惑,谁能解释一下 ConcurrentHashMap (jdk1.6.0_16) 中 HashEntry 的上述 java 文档。为什么需要额外的预防性锁定?

最佳答案

在Java 1.5发布的时候,JMM中有一条规定,HashEntry可以部分初始化。也就是说,当线程放入映射时,将创建 HashEntry 并将其分配为对桶头或 collison 成员的引用。当时条目的值,可能还没有被分配给其他线程看到。

CHM 假定如果条目不为空,则该值不应该为空,因此将 readValueUnderLock 作为故障保险。

我向 DL 询问了这个确切的情况,他说尽管有可能发生,但永远不应该发生。他还说,从 1.6 开始,这个问题就不会发生了。

关于java - 在数据竞争期间,线程能否读取 volatile 变量的初始空值?特别是在构造函数中为其分配了非空值时?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4343234/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com