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



下面的代码是否总是打印出data的"正确"值?即使在方法setData中赋值给datadataReady之间存在其他操作?

或者JVM可以重新排序这些操作,使得RunningThread可以看到dataReady为真,而data仍然为空?

如果代码是安全的&正确——volatile字段是如何防止重新排序问题的呢?这是否意味着data本身甚至不需要是volatile的,仅仅使dataReady volatile会导致JVM不缓存实例的其他字段的本地值,其中一个字段是volatile的?

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语言规范的措辞是:

如果xy是同一个线程的动作,并且x在程序顺序上位于y之前,则hb(x, y)

如果 hb (x, y) hb (y, z) ,然后 hb (x, z)

volatile字段(§8.3.1.4)的写入发生在字段的每次后续读取之前。

所以写入data 发生在之前,同一个线程写入dataReady发生在之前,第二个线程读取dataReady发生在之前,第二个线程读取data

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

最新更新