單例模式中的同步鎖
阿新 • • 發佈:2019-01-31
單例模式的編寫有多種方式,但是有些細節的地方容易被大家忽略,在這裡我簡單的向大家分享一下,如有不正確的地方,還望指正。
經典的單例模式有兩種方式一種是餓漢式,一種是懶漢式。
先來提一下餓漢式,這個是最簡單但是最不實用的。
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;
}
}