C++用多種方式實現Singleton單例模式

乞力馬紮羅的雪CYF發表於2015-08-24

題目:設計一個類,只能生成該類的一個例項。

(1)解法一:只適用於單執行緒環境

由於要求只能生成一個例項,因此我們必須把建構函式設為私有函式以禁止他人建立例項。我們可以定義一個靜態的例項,在需要的時候建立該例項。

public class Singleton1{

  private Singleton1(){
  
  }
  
  private static Singleton1 instance = NULL;
  
  public static Singleton1 funcInstance{
  
    get{
    
      if(instance == NULL){
      
        instance = new Singleton1();
      }
     
      return instance;
      
    }
  }

  
}

上述程式碼在Singleton1的靜態方法funcInstance()中,只有在instance為null的時候才建立一個例項以避免重複建立,同時把建構函式定義為私有函式,這樣才能確保只建立一個例項。



(2)解法二:雖然能在多執行緒環境中能工作但是效率不高

解法一中的程式碼在單執行緒的時候工作正常,但是在多執行緒的情況下就有問題了。假設兩個執行緒同時執行到判斷instance是否為null的if語句,並且instance的確沒有建立時,那麼兩個執行緒都會建立一個例項,此時就不再滿足單例模式的要求了。

為了保證在多執行緒環境下我們還是隻能得到型別的一個例項,需要加上一個同步鎖。實現如下:

public class Singleton2{

  private Singleton2(){
  
  }
  
  private static readonly object syncObj = new object();
  
  private static Singleton2 instance = NULL;
  
  public static Singleton2 funcInstance{
  
    get{
      
      lock(sync){
      
        if(instance == NULL){
          
          instance = new Singleton2();
        }
        
      }
      
      return instance;
      
    }
  }

  
}

我們還是假設有兩個執行緒同時想建立一個例項。由於在一個時刻只有一個執行緒能得到同步鎖,當第一個執行緒加上鎖時,第二個執行緒只能等待。當第一個執行緒發現例項還沒有建立時,他建立出一個例項。接著第一個執行緒釋放同步鎖,此時第二個執行緒可以加上同步鎖,並執行接下來的程式碼。這個時候由於例項已經被第一個執行緒建立出來了,第二個執行緒就不會重複建立例項了。但是加鎖是一個比較耗時的操作,我們應該儘量避免。


(3)解法三:加同步鎖前後兩次判斷例項是否已存在

我們只是在例項還沒有建立之前需要加鎖操作,以保證只有一個執行緒建立出例項。而當例項已經建立之後,就不需要加鎖操作了。程式碼實現如下:

public class Singleton3{

  private Singleton3(){
  
  }
  
  private static readonly object syncObj = new object();
  
  private static Singleton3 instance = NULL;
  
  public static Singleton3 funcInstance{
  
    get{
      
      if(instance == NULL){
      
        lock(sync){
          
          if(instance == NULL){
            
            instance = new Singleton3();
          }
          
        }
        
      }
      
      return instance;
      
    }
  }

  
}

Singleton3中只有當instance為NULL即沒有建立時,需要加鎖操作。當instance已經建立出來後,則無需加鎖。因為只有第一次的時候instance為NULL,因此只有在第一次試圖建立例項的時候需要加鎖,這樣Singleton3的時間效率就比Singleton2好。


github主頁:https://github.com/chenyufeng1991  。歡迎大家訪問!





















相關文章