很多情況下需要將我們編寫的程式中的類在一定範圍內只保留乙個例項,例如出於效能考慮,我們不希望反覆例項化這個物件,用完了後再將它銷毀,然後又用到這個型別的某些服務,再例項化,用完了再銷毀,如此反覆,不如做個全域性的,例項化後,一直用到本程式功能結束,但是全域性的又有一些問題。
經典的singleton模式可以為我們提供乙個簡單的解決方案,他提供了乙個全域性訪問點,用來訪問這個唯一例項,簡單思想是:當外界想要持有這個型別的例項時,這個型別會自己檢查這個例項是否已經被建立,如果沒有則建立乙個並返回這個例項的指標/引用,有了,則簡單的返回這個物件的指標/引用即可。而且為了確保該型別的例項的唯一性,將建構函式protected或private。
單件模式的示例**如下:
singleton
... ;
singleton
*singleton::m_pinstance =0
;singleton
*singleton::getinstance()
...return
m_pinstance;
使用時,僅需要通過getinstance成員函式訪問這個單件,然後訪問這個型別的其他服務,這樣做最直接的好處就是避免了全域性變數帶來的汙染命名空間的問題,同時也避免了全域性物件的過早例項化的問題(因為全域性物件會在main執行前處理,所以不論我們的程式需不需要訪問這個型別,他都被例項化了,用singleton模式可以將他的例項化推遲到必需時)。
單件模式還可以與工廠模式連用,即可以在getinstance中判斷一下需要的到底是那一種單件,然後用乙個子類的物件返回給乙個基類的指標就可以了。不過這些場模式的例項必須遵循單件模式。
當然原型模式也可以連用,我之前有一篇blog介紹了我學mfc的時候做的乙個簡單的畫圖程式,當時用到了原型模式和場模式,裡面的畫筆和畫刷其實可以做成單件模式,這樣就不必在使用者每次切換畫筆或畫刷的時候new乙個pen或者brush了。
上面說的情況沒有考慮到執行緒問題,即如果存在多個執行緒要訪問我們這個類的那個例項,就會有這樣、那樣的問題:
1.如果第乙個執行緒訪問這個類時,m_pinstance == 0為true,那麼他要new乙個singleton的物件,恰巧第二個執行緒也訪問這個類,這是還沒有new 這個類的物件,而且m_pinstance也是空,那麼他也會new乙個singleton的物件,這就有問題,明明建立了兩個物件麼!析構時怎麼辦?只能記憶體洩露吧?
2.由於物件是唯一的,如果這個singleton有乙個方法是取得一組值,另乙個方法是遍歷這組值,不加鎖的情況下,可能會在第乙個執行緒遍歷到那組值的中間的時候,另乙個執行緒開始遍歷,在這樣比較背的情況下,你往下遍歷乙個,我往下遍歷乙個,就亂套了~
......
解決辦法就是在m_pinstance上加鎖,那麼類似第二種情況的問題就可以解決,但是第一種情況呢?我們需要做的可能就是對「檢查singleton物件已經被建立」進行同步。這麼做挺簡單,不過會造成乙個效能上的瓶頸,所有執行緒都必需等待檢查物件是否存在。也許這個物件已經早在800年前就建立了,不過還得鎖上-檢查-解鎖,浪費資源。另一種做法就是被稱為雙重檢查-鎖定的模式doublechecked locking!其意圖就是將上面的那些已經存在物件的情況的鎖上-檢查-解鎖的步驟省略掉。因此不會造成系統的瓶頸,問題只出現在第一次建立物件的時候,那麼就把他提取出來好了。示例**如下:
singleton
*singleton::getinstance()
...return
m_pinstance;
外層的if判斷檢查了已經存在例項的情況,內層的if判斷則是上面所描述的第一種情況的檢查。不過可惜,目前c++標準還沒有引入執行緒方面的庫,不知道boost中有沒有。
多執行緒Singleton單件模式
sina部落格http blog.sina.com.cn s blog 4c142e330100d2h9.html 單執行緒的singleton模式 public class singleton public static singleton instance 要點 多執行緒的singleton模式...
執行緒安全的單件模式(單例模式)
1.定義 某乙個類只有乙個例項,並且這個例項是在類內部進行例項化,並向整個系統提供該例項。2.單例模式的通用 publicsealedclass singleton public static singleton getinstance public static void dosomething ...
多執行緒 單例模式
單例模式 是非常典型常用的一種設計模式 乙份資源只能被申 載一次 單例模式的方法建立的類在當前程序中只有乙個例項 資源的程式初始化的時候就去載入,後面使用的時候直接使用,使用的時候比較流暢,有可能會載入用不上的資源,導致程式初始化時間比較慢。include class single instance...