public class ThreadTest {
public static volatile int race = 0;
public static void increase() {
race++;
}
private static final int THREADS_COUNT = 20;
public static void main(String[] args) {
Thread[] threads = new Thread[THREADS_COUNT];
for (int i = 0; i < THREADS_COUNT; i++) {
threads[i] = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10000; i++) {
increase();
}
}
});
threads[i].start();
}
while (Thread.activeCount() > 1) {
Thread.yield();
}
System.out.println(race);
}
}
如果正確並發的話,最後的輸出結果應該是200000,但每次運行得到的結果都是一個小於200000的值
當getstatic指令把race的值渠道操作棧頂時,volatile關鍵字保證了race的值在此時是正確的,但是在執行自贈操作
的時候,其他線程可能已經把race的值加大了,而在操作棧頂的值就變成了國企的數據,所以最後執行的就可能把
較小的race值同步回主內存之中。
volatile boolean initialized = false;
線程A
public void init() {
initialized = true;
}
線程B
while(!initialized){
sleep();
}
如果沒有用volatile修飾,就可能由於指令重排序的優化,導致線程A中的
initialized = true;
被提前執行了,這樣線程B中使用配置信息的代碼就可能錯誤
volatile關鍵字就可以避免此類情況的發生