简体   繁体   English

在数据竞争期间,线程是否可以读取volatile变量的初始空值? 特别是在构造函数中为它赋给非null值时?

[英]During a data race can a thread ever read initial null value of volatile variable? especially when a non null value is assigned to it in constructor?

  • What puzzles me is this. 令我困惑的是这个。

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

...Because the value field is volatile, not final, it is legal wrt the Java Memory Model for an unsynchronized reader to see null instead of initial value when read via a data race. ...因为值字段是易失性的,而不是最终的,所以对于非同步读取器而言,Java内存模型在通过数据争用读取时看到null而不是初始值是合法的。 Although a reordering leading to this is not likely to ever actually occur, the Segment.readValueUnderLock method is used as a backup in case a null (pre-initialized) value is ever seen in an unsynchronized access method. 尽管实际上不可能实现重新排序,但是如果在非同步访问方法中看到null(预初始化)值,则将Segment.readValueUnderLock方法用作备份。

  • here is the implementation of get method of ConcurrentHashMap#Segment 这里是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; } 
  • And of readValueUnderLock 和readValueUnderLock


V readValueUnderLock(HashEntry e) {
        lock();
        try {
            return e.value;
        } finally {
            unlock();
        }
    }
  • Based of my reading and understanding every thread will read an up to date value of volatile variable. 根据我的阅读和理解,每个线程都会读取volatile变量的最新值。

  • So when will a thread read initial null value? 那么什么时候线程会读取初始空值? especially in HashEntry where value is assigned before the constructor completes. 特别是在HashEntry中,在构造函数完成之前赋值。 (Also note that HashEntry's reference never escapes its constructor.) (另请注意,HashEntry的引用永远不会转义其构造函数。)

  • I am stumped, can some one explain the above java doc of HashEntry in ConcurrentHashMap (jdk1.6.0_16). 我很难过,有人可以在ConcurrentHashMap(jdk1.6.0_16)中解释上面的HashEntry java doc。 and why that extra precaution locking is required? 为什么需要额外的预防措施?

When Java 1.5 was released, there was a provision in the JMM that said that the HashEntry can be partially initialized. 当Java 1.5发布时,JMM中有一条规定可以部分初始化HashEntry。 That is, when a thread is putting into the map, the HashEntry is created and assigned as a reference to either the bucket head or a collison member. 也就是说,当线程放入地图时,会创建HashEntry并将其指定为对桶头或collison成员的引用。 At that time the value of the entry, may have not been assigned to be seen by the other threads. 此时,条目的值可能尚未分配给其他线程。

The CHM assumes that if the entry isnt null, then the value shouldn't be null so readValueUnderLock was put in as a failsafe. CHM假定如果条目不为null,则该值不应为null,因此readValueUnderLock作为故障保护放入。

I asked DL about this exact situation and he said that despite the possibility of it happening, it never should. 我向DL询问了这个确切的情况,他说虽然有可能发生这种情况,但它永远都不应该。 He also said that since 1.6, that issue won't happen. 他还说,自1.6以来,这个问题不会发生。

You must make sure that the reference to the Map cannot be used by anyone, before the constructor completes. 在构造函数完成之前,您必须确保任何人都不能使用对Map的引用。 That should be easy to do when it is a private field and only accesses by getter methods - including in the class where that field is held. 当它是一个私有字段并且只能通过getter方法访问时应该很容易做到 - 包括在保存该字段的类中。

The constructor will finish before the instance getter method will be able to be called. 构造函数将在实例getter方法被调用之前完成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从未分配null的volatile变量可以包含null吗? - Can a volatile variable that is never assigned null to ever contain null? 在从另一个线程读取期间是否可以读取非易失性变量的陈旧值? - Is it possible to read stale value of non-volatile variable during read from another thread? 是否可以为值分配或与值类型变量进行比较? - Can null be assigned to or be compared to a value type variable? 由该类的方法延迟分配的非易失性变量不能被另一个线程读取吗? - Can a non-volatile variable that is delayed assigned to by a method of the class not be read by another thread? java,什么时候(以及多长时间)线程可以缓存非易失性变量的值? - java, when (and for how long) can a thread cache the value of a non-volatile variable? 清单 <Class> 变量即使分配了值也返回null - List<Class> variable returns null even when assigned a value wait()期间的非易失性变量值和两个线程中的notifyall()调用 - Non-volatile variable value during wait() and notifyall() call in 2 threads 在java中初始化后,volatile映射是否可以为null? - is the volatile map can be null after initial in java? 加载构造函数时值为空 - Value is null when loading constructor 在Java中,构造函数中的&#39;this&#39;是否可以为null? - In Java, can 'this' be ever null inside the constructor?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM