以下代码是否会打印出"更正" 数据的价值?即使在方法 setData 中将值分配给数据和 dataReady 之间还有其他操作?
或者JVM是否可以重新订购这些操作,以便 RunningThread 可以看到 dataReady 为真,而数据仍为空?
如果代码是安全的&对于一个阻止重新排序问题的易失性字段,它是什么?这是否意味着数据本身甚至不需要是易变的,只有使 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;
}
}
}
答案 0 :(得分:3)
在写入volatile
变量之前,线程执行的所有写操作在读取前一个线程已写入的volatile
变量的值后,将对另一个线程可见。
Java Language Specification的措辞是:
如果 x 和 y 是同一个线程的操作, x 按照程序顺序出现在 y 之前,然后 hb(x,y)。
...
如果 hb(x,y)和 hb(y,z),那么 hb(x,z)。
...
对
volatile
字段(§8.3.1.4)的写入发生在每次后续读取该字段之前。
所以对data
的写入发生在同一个线程写入dataReady
发生之前 - 第二个线程读取{{1 发生在第二个线程读取dataReady
之前。
换句话说,关于data
变量的内存可见性保证足以保证读取dataReady
,甚至不必将data
声明为data
}。