本文假設有乙個manager管理類,**單例類懶漢/餓漢模式的實現,和單例類的多執行緒安全性,最後介紹meyers singleton寫法。
當第一次要用單例類的時候,再產生例項。是一種典型的拖延(lazy)策略。
類宣告:
class manager
;
類定義:
//單例物件指標初始化為nullptr,防止指向了未定義的資料
manager* manager::s_manager = nullptr;
//提供單例類物件訪問
manager* manager::getinstance()
//刪除單例類
void manager::deleteinstance()}
void manager::dosomething()
使用此類時就可以通過:
manager::getinstance()->dosomething();
來運用單例類來做某些操作了。
上面的例子,並不能保證執行緒安全。
假如沒有例項時,某兩個執行緒都幾乎同時使用getinstance(),那麼很可能會產生2份例項,其中乙份還會變成洩露的記憶體。
為了解決執行緒安全問題,本文使用了c++11的
std::mutex
作為互斥鎖,在類額外增加了乙個靜態變數std::mutext s_mtx;
。
//提供單例類物件訪問
manager* manager::getinstance() //解鎖
return s_manager;
}//刪除單例類
void manager::deleteinstance()
}//解鎖
}
為什麼不是(上鎖,檢查,操作,解鎖)或者(檢查,上鎖,操作,解鎖),而是使用了雙重檢查(檢查,上鎖,檢查,操作,解鎖)?
上鎖的成本遠遠比檢查空指標要高,且當需要產生例項時才需要鎖操作。而實際上大量多次使用getinstance時(因為已經產生了例項)並不需要上鎖,若先上鎖,則會嚴重造成效能阻塞。
僅僅是檢查後再上鎖,則根本沒有做到任何執行緒安全。
餓漢模式與懶漢模式相反,一開始就生成唯一例項。這樣就不用檢查是否存在例項,而且也無需考慮產生例項時的執行緒安全。
class manager ;
//提供單例類物件訪問
manager* manager::getinstance()
使用方法:
manager::getinstance()->dosomething();
可以看到**比懶漢模式簡單多了。在大量使用檢查空指標造成的效能瓶頸而記憶體始終充足時,可以考慮使用餓漢模式
目前最推薦的c++單例寫法
class manager
private:
manager();
manager(manager const&);
manager& operator = (manager const&);
~manager();
};
這段**很簡單,雖然看上去和懶漢模式類似,只是static變數的位置從類移動到了例項獲取函式內。但是實際上由於c++的機制,當第一次呼叫該函式時,例項才會被構建出來。這樣既可以得到餓漢模式的執行緒安全,又可以有懶漢模式的按需分配的功能。
單例類設計模式算是比較經典的乙個模式,但是需要注意,它並不是想象中那麼美好。
它是一種換皮的全域性變數。
它促進了耦合。
它可能對併發不友好(取決於你使用的單例寫法)。
一些替代方案:
當你僅需要全域性可見的方法時,應該用類靜態方法而不是乙個類例項。
盡可能為例項提供其它便捷的訪問方式(傳參/基類獲取/服務定位器獲取等),而不是通過提供全域性可見的訪問方式。
如果你只是需要類保證只有唯一物件而不需要全域性性,那麼應對外封閉獲取例項介面(其實就是不可全域性獲取例項的)。
所以要注意單例類設計模式不應被泛用,通過上面的替代方案多多少少也就減少了很多不必要的單例設計。
C 設計模式 單例設計模式
對於單例設計模式做乙個簡單的記錄。使用場景 如果乙個類在整個程式的執行環境中,有且僅需乙個例項,可以使用單例設計模式。singleton模式主要設計思路就是用private 或 protected 修飾建構函式,並在全域性維護唯一的例項,通過介面向外部提供這個例項。下面是簡單的 實現。singlet...
C 設計模式 單例設計模式
效果 實現步驟 將建構函式私有化。在類中定義乙個靜態的指標變數 一般設為私有 並在類外初始化為空 定義乙個返回值為類指標的靜態成員函式,如果2中的指標物件為空,則初始化物件,以後再有物件呼叫該靜態成員函式的時候,不再初始化物件,而是直接返回物件,保證類在記憶體中只有乙個例項。解釋 include u...
C 單例設計模式螢幕類練習
題目內容 以單例模式建立乙個螢幕screen物件。輸入格式 用空格分開的兩個整數,代表螢幕解析度 輸出格式 用空格分開的兩個整數,代表螢幕解析度。隨後有換行符 輸入樣例 800 600 輸出樣例 800 600 具體要求 請將如下 中的缺失部分補全 補全screen類中的資料域成員,給出適當的資料型...