c 單列模式與執行緒安全

2022-05-02 15:48:10 字數 1926 閱讀 9379

通常c++裡面的單列模式很容易實現,我們也不需要去考慮其執行緒安全的問題,但是在多執行緒環境中我們卻必須要考慮到。首先我們來分析下一下的這個單列模式為什麼不是執行緒安全的,通常的單列模式寫法:

class

msgofarrival

;msgofarrival* msgofarrival::m_pinstance =null;

msgofarrival::msgofarrival(

void

)msgofarrival::~msgofarrival(void

)

假設兩個多執行緒同時執行getinstance()函式,那麼m_pinstance==null時, 兩個執行緒同時進入了if中時就會建立兩個指標,這當然是不行的。解決這個問題首先我們會想到加鎖,如改成
msgofarrival*msgofarrival::getinstance()

return

m_pinstance;

}

這樣當然可以,而且m_pinstance一但new成功,getinstance呼叫不會在進入if中,所以大量呼叫該單列並不會因為臨界區造成效能瓶頸。

第二種方法是靜態變數初始化的時候,我們直接讓其new乙個指標,因為我們知道靜態變數是在main函式還沒執行的時候就由主線程完成了初始化,既然單例指標還沒進入到main就已經構造了, 那麼我們當然不需要在進入main以後的多執行緒中來擔心單例構造的執行緒安全性。**如下:

class

msgofarrival

;const msgofarrival* msgofarrival::m_pinstance = new

msgofarrival;

msgofarrival::msgofarrival(

void

)msgofarrival::~msgofarrival(void

)const msgofarrival*msgofarrival::getinstance()

需要注意m_pinstance使用const進行修飾的,其所指物件是const的也就是說我們不能修改這個單列物件,這也要求我們在呼叫改單列的函式時該函式也必須是const的如:

int getdata() const;  //

函式宣告

//函式定義

int msgofarrival::getdata() const

當然m_pinstance也可以不用const修飾, 但是這樣其其內部資料可以被修改, 這樣在多執行緒的時候是很危險的。

上面單例模式已經是執行緒安全的, 但是有個問題, 這個單例被建立後如何釋放呢?第一種方法 在在類裡面增加乙個靜態的函式用於釋放指標,這樣做在程式中我們隨時可以釋放單例指標。但是有時候我們的單例指標要一直伴隨著程序結束,這個時候我們就可以採用第二種方法:

class

msgofarrival

};

static cgarbo garbo; //

清理資源

msgofarrival(void

);

static

const msgofarrival*m_pinstance;

};//

注意靜態物件也必須想變數一樣初始化,否則這個靜態物件不存在,也就不會去執行析構函式

msgofarrival::cgarbo msgofarrival:: garbo; //

清理資源

我們在類裡面新增了乙個cgarbo類,這個類只有乙個作用負責清除單列物件指標,定義乙個static的garbo物件, 該物件宣告週期與單例物件指標是一樣的,這個靜態garbo物件也會在程式結束時釋放,這個時候會將單例指標所擁有資源也釋放掉。注意safe_delete是我自己定義的釋放巨集。

單列模式與多執行緒

在23個標準設計模式中,單例模式在應用中還是很常見的,但是在多執行緒環境中,單例模式的使用有非常多的坑,使用好單例模式的乙個原則 如何使單例模式在遇到多執行緒的環境中是安全的 正確的。下面分析幾種多執行緒的實現方式以及遇到的坑。立即載入 實用類的時候已經將物件建立完畢,常見的是直接new例項化,有 ...

C 單列模式

在 design patterns elements of resuable object oriented software 中的定義是 ensure a class only has one instance,and provide a global point of access to。它的主...

c 單列模式

借鑑了劍指offer書上寫的和乙個部落格 c 單例模式。自己做乙個簡單的總結。只能有乙個例項化的物件的類。那麼如何做到只有乙個例項化物件呢?建構函式一般定義在public之中,你也可以定義在protected和private之中,這樣的話就沒有辦法進行外部例項化。有的時候,會要求禁止使用者建立類的例...