我們都很清楚乙個簡單的單例模式該怎樣去實現:建構函式宣告為private或protect防止被外部函式例項化,內部儲存乙個private static的類指標儲存唯一的例項,例項的動作由乙個public的類方法代勞,該方法也返回單例類唯一的例項。
上**:
class singleton
private:
static singleton* p;
public:
static singleton*
instance()
;};singleton* singleton:
:p =
null
;singleton* singleton:
:instance()
這是乙個很棒的實現,簡單易懂。但這是乙個完美的實現嗎?不!該方法是執行緒不安全的,考慮兩個執行緒同時首次呼叫instance方法且同時檢測到p是null值,則兩個執行緒會同時構造乙個例項給p,這是嚴重的錯誤!同時,這也不是單例的唯一實現!
單例大約有兩種實現方法:懶漢與餓漢。
懶漢:故名思義,不到萬不得已就不會去例項化類,也就是說在第一次用到類例項的時候才會去例項化,所以上邊的經典方法被歸為懶漢實現;
餓漢:餓了肯定要飢不擇食。所以在單例類定義的時候就進行例項化。
特點與選擇:
由於要進行執行緒同步,所以在訪問量比較大,或者可能訪問的執行緒比較多時,採用餓漢實現,可以實現更好的效能。這是以空間換時間。
在訪問量較小時,採用懶漢實現。這是以時間換空間。
執行緒不安全,怎麼辦呢?最直觀的方法:加鎖。
這裡使用雙重鎖定,通過越過了if (instance == null)的執行緒才會有進入鎖定臨界區的可能性,這種機率還是比較低的,不會阻塞太多的執行緒,但為了防止乙個執行緒進入臨界區建立例項,另外的執行緒也進去臨界區建立例項,又加上了一道防禦if (instance == null),這樣就確保不會重複建立了。
方法1:加鎖的經典懶漢實現:
class singleton
private:
static singleton* p;
public:
static pthread_mutex_t mutex;
static singleton*
initance()
;};pthread_mutex_t singleton:
:mutex;
singleton* singleton:
:p =
null
;singleton* singleton:
:initance()
return p;
}
方法2:內部靜態變數的懶漢實現
此方法也很容易實現,在instance函式裡定義乙個靜態的例項,也可以保證擁有唯一例項,在返回時只需要返回其指標就可以了。推薦這種實現方法,真得非常簡單。
class singleton
public:
static pthread_mutex_t mutex;
static singleton*
initance()
;int a;};
pthread_mutex_t singleton:
:mutex;
singleton* singleton:
:initance()
為什麼我不講「執行緒安全的餓漢實現」?因為餓漢實現本來就是執行緒安全的,不用加鎖。為啥?自己想!
class singleton
//把複製建構函式和=操作符也設為protected,防止被複製
singleton
(const singleton&);
singleton& operator=
(const singleton&);
private:
static singleton* p;
public:
static singleton*
initance()
;};singleton* singleton:
:p = new singleton;
singleton* singleton:
:initance()
是不是特別簡單呢?
以空間換時間,你說簡單不簡單?
在這裡有乙個問題需要說明:
我們看到建構函式是私有的,按照道理是不能在類外訪問的,但是可以看到singleton* singleton::p = new singleton;
這句**其實在類外訪問了私有的建構函式
還有乙個問題需要說明的是,static singleton* p;
是私有的singleton* singleton::p = new singleton;
還在類外訪問了私有的p
以上兩條違反了c++的訪問控制規則,但是c++還規定,static 成員只能在類外進行初始化,所以我們必須在類外初始化p,又因為p是singleton的指標,初始化它必須呼叫建構函式,所以我們就看到了上面的非常特殊的寫法singleton* singleton::p = new singleton;
需要注意的是,只有在初始化私有靜態成員的時候才能在類外訪問私有的靜態成員。也只有在初始化物件靜態指標的時候這種特殊情況才能呼叫私有的建構函式。總之,這種情況十分特殊。
面試的時候,執行緒安全的單例模式怎麼寫?肯定怎麼簡單怎麼寫呀!餓漢模式反而最懶[正經臉]!
c++的單例模式與執行緒安全單例模式(懶漢/餓漢)
c++靜態變數,靜態函式,私有靜態變數的使用小記
單例模式及c 實現
昨天面試 面試官讓我寫個單例模式,一時語塞。慚愧設計模式沒看好,回來研究了一下,在單例模式建構函式是可以private的,用靜態成員函式getinstance來獲得例項。單例模式 作為物件的建立模式,單例模式確保某乙個類只有乙個例項,而且自行例項化並向整個系統提供這個例項。這個類稱為單例類。單例模式...
C 實現單例模式
給所需要進行單例的類ctest的建構函式宣告為private或者protected 防止在類外隨意生成ctest的物件 然後宣告乙個靜態成員變數 instance 乙個靜態成員函式getinsance staticctest getinstance staticctest instance 靜態成員...
C 實現單例模式
ifndef singleton h define singleton h include include using namespace std class locker inline locker inline void lock inline void unlock private pthre...