连续为多个可变字段赋值的操作是否可以重新排序?

Can operations, which assign values to multiple volatile fields consecutively, be reordered?

下面的代码是否总是打印出 data 的 "correct" 值?即使在方法 setData?[= 中将值分配给 datadataReady 之间还有其他操作11=]

或者 JVM 是否可以想象地重新排序这些操作,以便 RunningThread 可以将 dataReady 视为 true 而 data 仍然为空?

如果代码安全且正确 - 防止重新排序问题的 volatile 字段是什么?这是否意味着 data 本身甚至不需要易失性,只是让 dataReady 易失性导致 JVM 不缓存一个实例的其他字段的本地值,其中一个字段是易变的?

public class RunningThread implements Runnable {

private volatile boolean dataReady = false;
private volatile String data = null;

public void run() {
    while (!dataReady){
        //Do stuff or wait
    }
    System.out.println("Value of data '" +data +"' is definitely not null.");
}


//setData called by another thread
public void setData(String dataToSet){
    if (dataToSet!=null){
        data = dataToSet;
        dataReady = true;
    }
}

}

一个线程在写入 volatile 变量之前执行的所有写入在从前一个线程写入的 volatile 变量中读取值后将对另一个线程可见。

Java Language Specification的写法是:

If x and y are actions of the same thread and x comes before y in program order, then hb(x, y).

If hb(x, y) and hb(y, z), then hb(x, z).

A write to a volatile field (§8.3.1.4) happens-before every subsequent read of that field.

因此写入 data 发生在 同一线程写入 dataReady 发生在 [=34= 之前] 第二个线程读取 dataReady 发生在 之前,第二个线程读取 data.

换句话说,dataReady变量的内存可见性保证足以保护data的读取,甚至不需要将data声明为volatile.