您遇到的問題是,您沒有足夠長的時間來優化代碼並緩存值。
當x86_64系統上的線程第一次讀取值時,它將獲得線程安全副本。它只能在以後的變化中看不到。其他CPU可能不是這種情況。
如果您嘗試此操作,則可以看到每個線程都卡住了其本地值。
public class RequiresVolatileMain {
static volatile boolean value;
public static void main(String... args) {
new Thread(new MyRunnable(true), "Sets true").start();
new Thread(new MyRunnable(false), "Sets false").start();
}
private static class MyRunnable implements Runnable {
private final boolean target;
private MyRunnable(boolean target) {
this.target = target;
}
@Override
public void run() {
int count = 0;
boolean logged = false;
while (true) {
if (value != target) {
value = target;
count = 0;
if (!logged)
System.out.println(Thread.currentThread().getName() + ": reset value=" + value);
} else if (++count % 1000000000 == 0) {
System.out.println(Thread.currentThread().getName() + ": value=" + value + " target=" + target);
logged = true;
}
}
}
}
}
打印下面顯示其fliling值,但卡住了。
Sets true: reset value=true
Sets false: reset value=false
...
Sets true: reset value=true
Sets false: reset value=false
Sets true: value=false target=true
Sets false: value=true target=false
....
Sets true: value=false target=true
Sets false: value=true target=false
如果我添加-XX:+PrintCompilation
此開關發生了時間,你看到
1705 1 % RequiresVolatileMain$MyRunnable::run @ -2 (129 bytes) made not entrant
1705 2 % RequiresVolatileMain$MyRunnable::run @ 4 (129 bytes)
這表明代碼已經被編譯爲本地是不是線程安全的方式。
,如果你讓volatile
你看到它不斷地翻轉值的值(或直到我厭倦)
編輯:這是什麼做的測試是;當它檢測到的值不是那個線程目標值時,它設置該值。即。線程0設置爲true
,線程1設置爲false
當兩個線程正確共享字段時,他們會看到對方發生更改,並且值不斷在true和false之間翻轉。
沒有volatile會失敗,每個線程只能看到它自己的值,所以它們都改變了值,線程0看到true
,線程1看到false
爲同一個字段。
簡短的回答沒有。但是你真的需要檢查在有人告訴你之後從屋頂跳下是否危險,並給出了充分的理由嗎? – Voo
使用2芯電腦。 –
@Voo ...你到底在說什麼? –