單例模式中的同步鎖

單例模式的編寫有多種方式,但是有些細節的地方容易被大家忽略,在這裏我簡單的向大家分享一下,如有不正確的地方,還望指正。

經典的單例模式有兩種方式一種是餓漢式,一種是懶漢式。

先來提一下餓漢式,這個是最簡單但是最不實用的。

public class SingleTone {
		
	private SingleTone(){
			
	}
		
	private static SingleTone single = null;
		
	//餓漢式
	public static SingleTone getInstance(){
		single = new SingleTone();
		return single;
	}
}

下面是比較簡單的懶漢式編寫,主要是爲了保證創建的對象只有一個。

public class SingleTone {
		
	private SingleTone(){
			
	}
	private static SingleTone single = null;
	//懶漢式
	public static SingleTone getInstance(){
		if(single==null){
			single = new SingleTone();
		}
		return single;
	}
}

這種懶漢式存在線程安全問題,所以需要加同步鎖,加同步鎖,則有兩種方式,一種是將synchronized加在方法上,另一種是將synchronized加在方法內。

public class SingleTone {
	
	private SingleTone(){
		
	}
	private static SingleTone single = null;
	public synchronized static SingleTone getInstance(){
		if(single==null){
			single = new SingleTone();
		}
		return single;
	}
}

但是,synchronized加在方法會使效率低,因爲鎖的範圍比較大,我們要向保證是單例的,其實主要是爲了保證single = new SingleTone();是線程安全的就行,所以在加鎖的時候,我們一般會將鎖加到方法裏面。

public class SingleTone {
	
	private SingleTone(){
		
	}
	private static SingleTone single = null;
	public static SingleTone getInstance(){
		if(single==null){
			synchronized (SingleTone.class) {
				single = new SingleTone();
			}
		}
		return single;
	}
}

將鎖加到裏面後又會有新的問題,如果兩個線程同時進入了getInstence()中後,並都判斷了single等於null,其中一個進入同步鎖中,另外一個在門口等待,當一個創建完對象後讓出鎖,另一個直接進去,這樣它就會又創建對象,所以更好的方式是加雙重鎖定,這種方式是效率高,並且安全。

public class SingleTone {
	
	private SingleTone(){
		
	}
	
	private static SingleTone single = null;
	
	public static SingleTone getInstance(){
		if(single==null){
			synchronized (SingleTone.class) {
				if(single==null){
					single = new SingleTone();
				}
			}
		}
		return single;
	}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章