java關鍵字volatile和synchronized在多線程中的應用

以前沒有弄懂validate和synchronized,藉此新開博之際記錄下。

volatile(不穩定):java關鍵字用來修飾變量,不可用來修飾方法。

在java語法中對於變量值讀寫的操作,除了long和double都是原子性操作。其原因是在一些jvm中處理的原子爲4bytes,基本類型(jvm處理2種類型一種是基本類型primitive,一種是引用類型reference)一般都是4bytes,long和double是8bytes。jvm對於數據的操作是遵循原子性的如果不以volatile修飾long和double,如果多線程訪問該變量,由於long操作的整體非原子性而導致結果混亂。所以long和double在讀寫的時候都需要被修飾volatile,而其他的類型在讀寫的時候則不需要被volatile修飾。比如:int,一個線程寫入4,另一個寫入5. 最後肯定是4或者5.而 long型,可能就是個亂七八糟的數值了。

在當前的jvm內存模型下,線程可以把變量放在本地內存中,而不是直接寫到主存中。但是在別的線程中就有可能在寄存器中讀取而主存中的數據已經改變,因此產生了不同步的情況。這個也是用volatile的另一個原因,經過volatile修飾的變量都要在主存中進行讀取。當volatile修飾的變量被線程訪問的時候,jvm會強制線程從主存中讀取;當變量的值改變的時候,jvm會強制寫入主存。另外:volatile修飾的變量會屏蔽掉jvm中必要的代碼優化,所以在效率上會稍微低一點。

以上理論全部都建立在原子性操作的情況下,如果非原子性操作,例如n++,n=n+1等,則需要用synchronized進行修飾。

volatile修飾的變量,操作中含有非原子性操作:

public class ThreadTest extends Thread{
	private volatile static int num=0;
	public void run(){
		for(int i=0;i<10;i++){
			num++;
			/*try {
				this.sleep(3);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}*/
		}
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		byte m=1;
		m=(byte) (m>>1);
		Thread[] threads=new Thread[100];
		for(int i=0;i<threads.length;i++){
			threads[i]=new ThreadTest();
		}
		for(int i=0;i<threads.length;i++){
			threads[i].start();
		}            
                for(int i=0;i<threads.length;i++){
			threads[i].join();
		}
System.out.println("The result is "+ThreadTest.num);}}


————————————————————————————————

以上返回:The result is 986

用synchronized修飾

public class ThreadTest extends Thread{
	private volatile static int num=0;
	public static synchronized void plus(){
		num++;
	}
	public void run(){
		for(int i=0;i<10;i++){
			plus();
			//num++;
			try {
				this.sleep(3);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args) throws InterruptedException {
		// TODO Auto-generated method stub
		Thread[] threads=new Thread[100];
		for(int i=0;i<threads.length;i++){
			threads[i]=new ThreadTest();
		}
		for(int i=0;i<threads.length;i++){
			threads[i].start();
		}
		for(int i=0;i<threads.length;i++){
			threads[i].join();
		}
		System.out.println("The result is "+ThreadTest.num);
	}

}
輸出結果:1000

發佈了26 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章