1. 程式人生 > >面試-執行緒安全的單例模式

面試-執行緒安全的單例模式

在一次面試過程中,面試官提到設計模式中單例模式,並要求我手寫一個,於是我馬上寫出一個懶漢式-單例模式,如:

public class SingleDemo{
   private SingleDemo singleDemo = null;
   private SingleDemo(){
   }

   public SingleDemo getSingleDemo(){
       if(singleDemo == null){
            singleDemo = new SingleDemo();
       }
       
       return singleDemo;
   }
}

她看了一下,問這個是執行緒安全的嗎?於是我意識到她開始要將話題拉倒多執行緒方面了,很顯然這並不是一個執行緒安全的程式碼。如果在高併發的情況下,很可能出現兩個執行緒同時訪問getSingleDemo方法,並new出兩個SingleDemo例項。但是在最開始回答這是否是一個執行緒安全的時候,我回答可以通過執行緒同步來保證每個執行緒依次執行來保證執行緒依次訪問getSingleDemo方法,然後我也不知道自己在說什麼。但最會還是提出一個解決方案用synchronized+static修飾getSingleDemo方法,修改後程式碼如下:

public class SingleDemo{
   private static SingleDemo singleDemo = null;
   private SingleDemo(){
   }

   public static synchronized SingleDemo getSingleDemo(){
       if(singleDemo == null){
            singleDemo = new SingleDemo();
       }
       
       return singleDemo;
   }
}

,也可以這樣寫:

public class SingleDemo{
   private SingleDemo singleDemo = null;
   private SingleDemo(){
   }

   public SingleDemo getSingleDemo(){
       if(singleDemo == null){
           synchronized(SingleDemo.class){
                if(singleDemo == null){
                    singleDemo = new SingleDemo();
                }
            }
       }
       
       return singleDemo;
   }
}

這中間有扯到synchronized修飾靜態方法,非靜態方法時各有什麼區別,在這說明一下:

當synchronized修飾靜態方法時,因為靜態方法屬於類方法,即在類載入時靜態方法也同時載入,所以獲得的鎖是類的鎖。

當synchronized修飾非靜態方法時,因為非靜態方法屬於物件方法,所以獲得的鎖是物件的鎖。

因為類鎖和物件鎖不同,他麼不是互斥的。

最後提一下關於synchronized修飾this,object,*.class的區別。

synchronized(this)、synchronized(object)、synchronized(*.class)區別

下面單獨對同步程式碼塊的三種同步寫法做一下區別:

1.synchronized(this)就死鎖住當前this代表的物件,即物件鎖,通常指某一個類的例項物件。

2.synchronized(object)屬於物件鎖,object本身就包含this的情況。

this指代的是當前同步塊所在方法所在的類,當不需要引用別的類的時候。

object指代的是需要呼叫的類,引用了別的類,且需要處理多執行緒併發訪問時,object指代的是被引用的類。如果沒有引用別的類,則指代的就是同步塊所在方法所在的類本身。

3.synchronized(*.class)的作用其實和synchronized static方法作用一樣。Class鎖對類其作用,也就是對類所有物件例項起作用。