天天看點

《并發程式設計》--6.Java記憶體模型(JMM)的關鍵字volatile

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模式

繼續閱讀