c 版本之單例模式

2021-09-25 20:48:00 字數 2790 閱讀 8880

單例模式(singleton)是指乙個類僅有乙個例項物件,並且該類提供乙個獲得該例項物件的全域性訪問點,它包含三個關鍵元素:

元素一:提供private型別的建構函式

元素二:提供private型別的的靜態成員變數,以儲存唯一的例項物件;

元素三:提供獲得本類例項的全域性訪問點getinstance函式,它是靜態型別的

初級版本

根據這三個關鍵元素可以寫出乙個基本的單例模式,其**如下:

class

csinglton

//在析構函式中釋放例項物件

~csinglton()

}public:

//(3)獲得本類例項的唯一全域性訪問點

static csinglton* getinstance()

//例項已經存在,直接該例項物件

return pinstance;

}private:

static csinglton* pinstance;//(2)唯一例項物件

};//靜態成員變數,類外初始化例項物件

csinglton* csinglton::pinstance = null;

由於csinglton類的建構函式是私有的,外界無法建立例項物件,只能由類本身來建立;這裡由getinstance()全域性訪問點來建立唯一的例項物件;

下面我們可以建立測試**,判斷是否符合預期,測試**如下:

csinglton *pinstance1 = csinglton::getinstance();

csinglton *pinstance2 = csinglton::getinstance();

if (pinstance1 == pinstance2)

else

執行結果:

從測試結果可以看出,**執行符合基本預期;

多執行緒基礎版本

如果csinglton 類執行在多執行緒環境下,可能會導致該類建立兩個例項,並造成記憶體洩漏,原因分析如下:

因此我們可以改進我們的**,對getinstance內部增加同步機制,修改**如下:

class

csinglton

~csinglton()

}public:

//(3)獲得本類例項的唯一全域性訪問點

static csinglton* getinstance()

singlelock.unlock();

return pinstance;

}private:

static csinglton* pinstance;//(2)唯一例項物件

static ccriticalsection m_critsection;

};//靜態成員變數,類外初始化例項物件

csinglton* csinglton::pinstance = null;

ccriticalsection csinglton::m_critsection;

當乙個執行緒已經位於臨界區時,另乙個執行緒將會被阻塞,直到當前執行緒退出臨界區,另乙個執行緒才會進入,就可以解決多執行緒同步問題;

多執行緒高效版

在一般的多執行緒環境下,以上**就可以保證正確性,但是在高併發、訪問量很大的環境下,上述的**實現將對效能造成很大影響;因為每次呼叫getinstance都需要加鎖,解鎖,比較浪費時間,解決方案是採用雙重鎖定。getinstance多執行緒高效版**如下:

static csinglton* getinstance()

singlelock.unlock();

}//例項已經存在,直接該例項物件

return pinstance;

}

以上**實現過程叫做「double-check-locking(雙重鎖定)」,即我們不讓執行緒每次都加鎖,而僅在例項未被初始化時,才進行執行緒同步,不僅保證記憶體不洩漏,還大大提高訪問效能;

靜態初始化版本

這種版本不僅實現最簡單而且還避免多執行緒下的不安全性,其**如下:

class csinglton

~csinglton()

}public:

//獲得本類例項的唯一全域性訪問點

static csinglton* getinstance()

private:

static csinglton* pinstance;

};//程式執行初期就建立例項

csinglton* csinglton::pinstance = new csinglton;

餓漢式和懶漢式單例類在單例模式中,常常提到了餓漢式單例類和懶漢式單例類兩個詞,上面提到的「初級版本」「多執行緒基礎版本」 「多執行緒高效版」都是懶漢式單例類,而「靜態初始化版本」是餓漢式單例類,它們的區別主要如下:

餓漢式單例就是在程式執行之前就建立例項,不管最終程式中是否用到,都占用資源,形容飢不擇食的模樣;

懶漢式單例就是程式在第一次呼叫全域性訪問點時才例項物件;

餓漢式單例不需要考慮多執行緒的安全性,但是有可能導致資源浪費,懶漢式單例需要採用「雙重鎖定」才能保證系統效能和正確性;

採用何種方式,我們應該根據實際應用情況區別對待;

c 之單例模式

1 本篇主要討論下多執行緒下的單例模式實現 首先是 double check 實現方式 這種模式可以滿足多執行緒環境下,只產生乙個例項。templateclass dclsingleton return value protected dclsingleton dclsingleton const ...

C 之單例模式

1 c 單例模式的概念及作用 單例模式也稱為單件模式 單子模式,可能是使用最廣泛的設計模式。其意圖是保證乙個類僅有乙個例項,並提供乙個訪問它的全域性訪問點,該例項被所有程式模組共享。2 單例模式的實現原理 1 私有靜態指標變數實現 使用類的私有靜態指標變數指向類的唯一例項,並用乙個公有的靜態方法獲取...

c 多執行緒單例模式 C 設計模式之單例模式

單例模式 乙個類在記憶體中只有乙個物件 例項 並且提供乙個可以全域性訪問或者獲取這個物件的方法。這兩天學的,寫了個小例子,問了同事一些關於執行緒的問題,還有從網上查了一些資料。還犯了一些低階的錯誤。vs2017控制台輸出文字亂碼,從網上找了一些方法不管用,最後發現是自己新建專案選錯模板了,選擇了.n...