连续为多个可变字段赋值的操作是否可以重新排序?
Can operations, which assign values to multiple volatile fields consecutively, be reordered?
下面的代码是否总是打印出 data 的 "correct" 值?即使在方法 setData?[= 中将值分配给 data 和 dataReady 之间还有其他操作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
.
下面的代码是否总是打印出 data 的 "correct" 值?即使在方法 setData?[= 中将值分配给 data 和 dataReady 之间还有其他操作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
.