Java語言規範中指出:為了獲得最佳速度,允許線程保存共享成員變數的私有拷貝,而且只當線程進入或者離開同步代碼塊時才與共享成員變數的原始值對比.
Volatile修飾的成員變數在每次被線程訪問時,都強迫從共享內存中重讀該成員變數的值.而且,當成員變數發生變化時,強迫線程將變化值回寫到共享內存.這樣在任何時刻,兩個不同的線程總是看到某個成員變數的同一個值.
下面是個例子:恢復註釋的任何一處都可以實現同步,就是讓程序停下來
Java代碼:
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run ?
public class StopThread {
// private static volatile boolean stopRequested; // value: false
private static boolean stopRequested; // value: false
public static void main(String... args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public synchronized void test () {
}
@Override
public void run() {
int i = 0;
while(!stopRequested){
// test();
i ;
}
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
當然最容易理解的是用同步的方法:
Java代碼:
import java.util.concurrent.TimeUnit;
// Broken! - How long would you expect this program to run ?
public class StopThread {
private static boolean stopRequested; // value: false
public static synchronized void requestStop() {
stopRequested = true;
}
public static synchronized boolean stopRequested() {
return stopRequested;
}
public static void main(String... args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while(!stopRequested())
i ;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
requestStop();
}
}
[火星人 ] java的volatile與多線程已經有477次圍觀