Java的記憶體模型(JMM)都是圍繞着原子性,有序性,可見性。一些特殊的場合下,需要用volatile等關鍵字保證這些特性。
當用volatile聲明一個變量時,就相當于告訴虛拟機,這個變量極有可能在多個線程中修改。為了確定這個變量被修改後,程式的所有線程都能夠意識到這個改動,虛拟機就必須采用一些特殊的手段,保證這個變量的可見性。
聲明的代碼如下:
static volatile int i = 0;
注意:volatile雖然能很大程度的維護原子性,但是不能替代鎖
一下一個簡單的demo即可說明
public class volatileMain1 {
static volatile int i = 0;
public static class Task implements Runnable {
@Override
public void run(){
for(int k=0;k<10000;k++){
i++;//如果是原子性的,最終的是為100000(10個線程累計加10)
//實際是小于100000的
//證明volatile不能代替鎖
}
}
public static void main(String[] args) throws InterruptedException {
Thread[] t = new Thread[10];
for(int i = 0;i<10;i++){
t[i] = new Thread(new Task());
t[i].start();
}
for(int i=0;i<10;i++){
t[i].join();
}
System.out.println(i);
}
}
}
實際的運作結果是小于100000的。。。
另外volatile也能保證資料的可見性和有序性,以後是一個簡單的demo
public class volatileMain2 {
private static boolean ready;
private static String name;
private static class ReaderThread extends Thread{
@Override
public void run(){
while(!ready);//虛拟機在client模式下,由于JIT并沒有做優化,主線程修改number,ReaderThread發現這個改動,退出程式
//虛拟機在server模式下,由于系統的優化,導緻ReaderThread永遠無法退出(因為readdy為false)
System.out.println("I am "+name);
}
}
public static void main(String[] args) throws InterruptedException {
new ReaderThread().start();
Thread.sleep(1000);
name = "yemt";
ready = true;
Thread.sleep(10000);
}
}
注意:可以使用Java虛拟機參數-server切換到Server模式