以下代碼有時會在我的Windows-PC和Mac上運行「valueWrapper.isZero()」,它們都在服務器模式下運行其JVM。 確定這是因爲值字段是不是最終的ValueWrapper類, 所以它可能是一些線程看到陳舊的值爲0Java內存模型中本地最終變量的語義?
public class ConcurrencyApp {
private final Random rand = new Random(System.currentTimeMillis());
private ValueWrapper valueWrapper;
private static class ValueWrapper {
private int value;
public ValueWrapper(int value) {
this.value = value;
}
public boolean isZero() {
return value == 0;
}
}
private void go() {
while (true) {
valueWrapper = new ValueWrapper(randomInt(10, 1024));
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
if (valueWrapper.isZero()) {
System.out.println("valueWrapper.isZero()");
}
}
});
thread.start();
}
}
private int randomInt(int min, int max) {
int randomNum = rand.nextInt((max - min) + 1) + min;
return randomNum;
}
public static void printVMInfos() {
String vmName = System.getProperty("java.vm.name");
System.out.println("vm name: " + vmName);
int cores = Runtime.getRuntime().availableProcessors();
System.out.println("available cores: " + cores);
}
public static void main(String[] args) {
ConcurrencyApp app = new ConcurrencyApp();
printVMInfos();
app.go();
}
}
但是,我們下面的修改,在這裏我使用了當地最後變量:
private void go() {
while (true) {
final ValueWrapper valueWrapper = new ValueWrapper(randomInt(10, 1024));
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
if (valueWrapper.isZero()) {
System.out.println("valueWrapper.isZero()");
}
}
});
thread.start();
}
}
現在看起來沒有線程看到的0 過時的值,但就是這個由JMM保證? 規範中的簡短說明並不能說服我。
你確定第一個代碼片段在線程之前沒有最後一行運行嗎? –
@DhanaKrishnasamy:它運行,因爲valueWrapper是ConcurrencyApp的一個字段 – user2867869