C++中的單例模式及按需釋放模型(五)
四、多執行緒安全的通用單例類例項獲取器
例子工程的名稱是SingletonThreadSafeInstanceGetter。
剛開始寫本文時,本沒有想實現多執行緒版本,主觀上以為同通常的單例模式一樣,多個多執行緒同步就可以了,很簡單,讓讀者自己開發就好了,不過後來真正去思考時發現不是那麼簡單的,感覺對此還是很有介紹的必要。
1、單例類例項與單例類例項獲取器例項的對應關係
在實現多執行緒安全的通用單例類例項獲取器前,將用3小節分析一些問題,然後再給出具體的實現。
在前面《C++中的單例模式及按需釋放模型(四)》已經給出了通用單例類例項獲取器,我們來想想實際使用的時候的具體情況,對於一個單例類SingletonExample,使用這個模型在系統中只可能存在一個例項,但是其單例類例項獲取器SingletonInstanceGetter有多少個例項呢,讀者如果仔細閱讀了前文,就會知道存在多個,也就是單例類例項同其例項獲取器例項的關係是一對多,當所有的這個單例類例項獲取器例項都釋放了的時候,這個單例類例項也會被釋放。
2、Windows中臨界區的使用方法
要使用Windows中的臨界區即CRITICAL_SECTION,一般都需要使用InitializeCriticalSection、EnterCriticalSection、LeaveCriticalSection、DeleteCriticalSection這4個API,具體函式含義這裡不講,如果不知道去查MSDN,這裡只說一下4個API的呼叫位置,假設有主執行緒M,然後建立2個子執行緒T1、T2,3個執行緒工作時需要用到一個臨界區C進行同步,那麼呼叫函式的位置將是M中呼叫InitializeCriticalSection初始化C,然後建立T1、T2,在M、T1、T2中使用EnterCriticalSection/LeaveCriticalSection對C進行操作來同步,然後等T1、T2退出後M中呼叫DeleteCriticalSection來清理C,這個過程說明了什麼,說明
A、InitializeCriticalSection/DeleteCriticalSection只在主執行緒中呼叫,工作中不會被呼叫,子執行緒不會呼叫這2個函式;
B、EnterCriticalSection/LeaveCriticalSection在工作中被呼叫,子執行緒只會呼叫到這2個函式。
3、如何在本單例模型中使用臨界區
基於以上兩點,我們分析在本單例模型中如何使用臨界區
A、需要獨立的臨界區物件
要使用臨界區,單例類例項獲取器SingletonInstanceGetter的GetInstance方法中使用EnterCriticalSection/LeaveCriticalSection這個沒有什麼疑問,我們在單例類例項獲取器SingletonInstanceGetter的構造和析構方法中使用InitializeCriticalSection/DeleteCriticalSection還是EnterCriticalSection/LeaveCriticalSection?這裡應該還是使用EnterCriticalSection/LeaveCriticalSection,因為單例類例項獲取器SingletonInstanceGetter的例項是線上程中建立和釋放的,即它的構造解構函式是線上程中呼叫的,如果構造和析構方法中使用InitializeCriticalSection/DeleteCriticalSection,就會多次初始化和清理臨界區,這是不可以的,那InitializeCriticalSection/DeleteCriticalSection在什麼地方呼叫呢?應該在單例類例項獲取器SingletonInstanceGetter的外部,即臨界區不屬於單例類例項獲取器,不是組合關係,是獨立於單例類例項獲取器的,只是被其使用,所以我們需要為使用的臨界區單獨建立類管理。
B、需要一個臨界區物件
那我們需要幾個臨界區物件呢?我們只需要一個,也就是對於一個單例類SingletonExample例項應該就對應一個臨界區物件,即臨界區物件也是一個單例類,同時對應多個單例類例項獲取器SingletonInstanceGetter例項,這樣既能保證多個單例類例項獲取器SingletonInstanceGetter例項工作時可以使用這個臨界區物件進行同步,同時不與其他單例類SingletonExampleTwo共用臨界區,互相干擾,造成不必要的等待。
C、臨界區物件的初始化和釋放
我們既然建立了臨界區物件,就可以在臨界區物件的建構函式中呼叫InitializeCriticalSection,解構函式中呼叫DeleteCriticalSection,正如【四.2】中講到的,這個臨界區物件的建立應該在主執行緒中完成,然後在多執行緒中使用這個物件,等執行緒都退出後,在主執行緒中釋放掉這個臨界區物件。
4、臨界區鎖定類
A、臨界區物件的實現
上面已經說明了臨界區和某個單例類例項是一一對應關係,所以我們也使用模板類的方式建立臨界區物件,模板引數就是單例類
臨界區模板類的定義與實現
template <typename T>
class SingletonThreadLock
{
friend SingletonInstanceGetter<SingletonThreadLock<T>>::SingletonInstanceGetter();
private:
SingletonThreadLock(void)
{
InitializeCriticalSection(&m_csLock);
}
public:
~SingletonThreadLock(void)
{
DeleteCriticalSection(&m_csLock);
}
public:
void Lock()
{
EnterCriticalSection(&m_csLock);
}
void Unlock()
{
LeaveCriticalSection(&m_csLock);
}
private:
CRITICAL_SECTION m_csLock;
};
不過多解釋,什麼位置呼叫什麼臨界區函式已經很明顯,而且通過私有建構函式和友元函式的方式把臨界區鎖定模板類定義成單例類。
B、臨界區物件的定義
這樣在使用中要定義臨界區單例例項就可以使用如下的方法
SingletonInstanceGetter<SingletonThreadLock<SingletonExampleOne>> sigOne;
SingletonThreadLock<SingletonExampleOne> *pscsOne = sigOne.GetInstance();
pscsOne就是單例類SingletonExampleOne對應的臨界區單例例項,啟動子執行緒前就應該在主執行緒中使用以上方法定義一個臨界區物件,因為是在主執行緒中呼叫,所以這裡不需要使用執行緒安全的單例類例項獲取器獲得臨界區物件,只需要使用SingletonInstanceGetter就可以了。
5、多執行緒安全的通用單例類例項獲取器
有了臨界區類了,我們就可以實現多執行緒安全的通用單例類例項獲取器了,其模板引數仍然是單例類,但是其建構函式需要多一個引數,就是這個單例類對應的臨界區物件,這樣才可以使用這個臨界區物件進行多執行緒同步
多執行緒安全的通用單例類例項獲取器類的定義與實現
template <typename T>
class SingletonThreadSafeInstanceGetter
{
public:
SingletonThreadSafeInstanceGetter(SingletonThreadLock<T> *pscsSingleton)
{
if (NULL == pscsSingleton)
{
m_pcsSingleton = NULL;
return;
}
m_pcsSingleton = pscsSingleton;
m_pcsSingleton->Lock();
if (m_pInstance == NULL)
{
try
{
m_pInstance = new T();
}
catch (...) //防止new分配記憶體可能出錯的問題,如果是記憶體分配錯誤異常為std::bad_alloc
{
m_pInstance = NULL;
}
}
//這裡不管SingletonExample建立成功與否都要加1
m_uiReference++;
m_pcsSingleton->Unlock();
}
~SingletonThreadSafeInstanceGetter(void)
{
if (NULL == m_pcsSingleton)
return;
m_pcsSingleton->Lock();
m_uiReference--;
if (m_uiReference == 0)
{
if (m_pInstance != NULL)
{
delete m_pInstance;
m_pInstance = NULL; //非常重要,不然下次再次建立單例的物件的時候錯誤
}
}
m_pcsSingleton->Unlock();
m_pcsSingleton = NULL;
}
public:
T *GetInstance()
{
if (NULL == m_pcsSingleton)
return NULL;
T *pInstance;
m_pcsSingleton->Lock();
pInstance = m_pInstance;
m_pcsSingleton->Unlock();
return pInstance;
}
private:
static T *m_pInstance;
static unsigned int m_uiReference;
SingletonThreadLock<T> *m_pcsSingleton;
};
template <typename T>
T *SingletonThreadSafeInstanceGetter<T>::m_pInstance = NULL;
template <typename T>
unsigned int SingletonThreadSafeInstanceGetter<T>::m_uiReference = 0;
SingletonThreadSafeInstanceGetter類同SingletonInstanceGetter類的不同主要有如下3點
A、增加一個例項成員變數m_pcsSingleton,即單例類對應的臨界區類SingletonThreadLock物件的指標成員;
B、SingletonThreadSafeInstanceGetter建構函式增加一個引數,這個引數就是單例類對應的臨界區類SingletonThreadLock物件的指標,建構函式中首先就會把這個指標賦值給m_pcsSingleton,然後進行其他工作;
C、SingletonThreadSafeInstanceGetter的構造、析構、GetInstance方法執行的功能都和SingletonInstanceGetter基本一樣,只是使用了單例類對應的臨界區類SingletonThreadLock物件進行了同步。
值得說明的一點是,這裡的多執行緒同步只是對於通過單例類例項獲取器獲取單例例項進行了同步,這個行為是多執行緒安全的,至於使用單例類時需要多執行緒同步,那必須開發人員在單例類中自己實現。
6、本模型多執行緒版本的使用方法
具體的單例類與《C++中的單例模式及按需釋放模型(四)》中的單例類SingletonExample基本相同,只是把那個友元宣告變成如下
friend SingletonThreadSafeInstanceGetter<SingletonExampleOne>::
SingletonThreadSafeInstanceGetter(SingletonThreadLock<SingletonExampleOne> *);
用於SingletonThreadSafeInstanceGetter就可以使用單例類SingletonExampleOne的私有構造方法建立物件了,如果需要這個單例類既能用於普通版本又能用於多執行緒版本,可以使用如下2句友元宣告即可
friend SingletonInstanceGetter<SingletonExampleOne>::SingletonInstanceGetter();
friend SingletonThreadSafeInstanceGetter<SingletonExampleOne>::
SingletonThreadSafeInstanceGetter(SingletonThreadLock<SingletonExampleOne> *);
至於單例類SingletonExampleOne的其他內容完全和前文的一樣,就不再列出程式碼,需要的請自己下載例子檢視。
現在模型的構件都有了,就可以使用類似如下程式碼來使用這個模型了
unsigned __stdcall SingltonThread(void* pArguments)
{
SingletonThreadLock<SingletonExampleOne> *pscsOne =
reinterpret_cast<SingletonThreadLock<SingletonExampleOne> *>(pArguments);
//獲取單例類例項
SingletonThreadSafeInstanceGetter<SingletonExampleOne>
sigSingletonInstanceGetter1(pscsOne);
SingletonExampleOne *pseSingleton1 = sigSingletonInstanceGetter1.GetInstance();
//使用單例類例項,使用過程中如果需要多執行緒同步,單例類自己實現
pseSingleton1->SetVariable(1);
//do something
_endthreadex(0);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE phThread[2] = {NULL, NULL};
unsigned threadID;
SingletonInstanceGetter<SingletonThreadLock<SingletonExampleOne>> sigOne;
SingletonThreadLock<SingletonExampleOne> *pscsOne = sigOne.GetInstance();
for (int i = 0; i < 2; ++i)
phThread[i] =
(HANDLE)_beginthreadex(NULL, 0, &SingltonThread, pscsOne, 0, &threadID);
WaitForMultipleObjects(2, phThread, TRUE, INFINITE);
for (int i = 0; i < 2; ++i)
CloseHandle(phThread[i]);
return 0;
}
在主執行緒中針對單例類SingletonExampleOne通過單例類例項獲取器獲取其對應的臨界區類SingletonThreadLock例項pscsOne,然後建立子執行緒,這裡建立了2個子執行緒,並把這個pscsOne作為引數傳遞(如果還需要傳遞其他內容,使用結構體等方式把其他內容和臨界區類例項一起作為引數)給子執行緒,子執行緒使用這個引數建立SingletonExampleOne對應的單例類例項獲取器SingletonThreadSafeInstanceGetter的例項,然後通過其方法GetInstance得到單例類SingletonExampleOne的例項,後面使用這個例項進行工作,子執行緒執行結束時,單例類SingletonExampleOne的例項就跟隨其單例類獲取器例項一起釋放掉了,等到所有子執行緒執行結束,主執行緒釋放sigOne時就會釋放臨界區物件pscsOne,整個過程並不難理解。
7、測試程式例子及輸出結果的分析
下面我們來看看具體的一個測試例子
程式如下
using dpex::SingletonInstanceGetter;
using dpex::SingletonThreadLock;
using dpex::SingletonThreadSafeInstanceGetter;
unsigned __stdcall LoopFreeSingltonThread(void* pArguments)
{
SingletonThreadLock<SingletonExampleOne> *pscsOne =
reinterpret_cast<SingletonThreadLock<SingletonExampleOne> *>(pArguments);
for (int i = 0; i < 100000; ++i)
{
{
SingletonThreadSafeInstanceGetter<SingletonExampleOne>
sigSingletonInstanceGetter1(pscsOne);
SingletonExampleOne *pseSingleton1 = sigSingletonInstanceGetter1.GetInstance();
//do something
}
}
_endthreadex(0);
return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dw1, dw2, dw3, dw4, dw5, dw6;
HANDLE phThread[5] = {NULL, NULL, NULL, NULL, NULL};
unsigned threadID;
SingletonInstanceGetter<SingletonThreadLock<SingletonExampleOne>> sigOne;
SingletonThreadLock<SingletonExampleOne> *pscsOne = sigOne.GetInstance();
cout << "現在開始測試,可能用時比較長,請耐心等待..." << endl << endl;
dw1 = GetTickCount();
for (int i = 0; i < 100000; ++i)
{
{
SingletonThreadSafeInstanceGetter<SingletonExampleOne>
sigSingletonInstanceGetter1(pscsOne);
SingletonExampleOne *pseSingleton1 = sigSingletonInstanceGetter1.GetInstance();
//do something
}
}
dw2 = GetTickCount();
for (int i = 0; i < 5; ++i)
phThread[i] =
(HANDLE)_beginthreadex(NULL, 0, &LoopFreeSingltonThread, pscsOne, 0, &threadID);
WaitForMultipleObjects(5, phThread, TRUE, INFINITE);
dw3 = GetTickCount();
for (int i = 0; i < 5; ++i)
CloseHandle(phThread[i]);
cout << "迴圈100000次新建釋放單例物件所用的時間為:" << dw2- dw1 << "毫秒" << endl;
cout << "5個執行緒,每個執行緒迴圈100000次新建釋放單例物件所用的時間為:" << dw3- dw2 <<
"毫秒" << endl;
cout << endl << "下面的測試,外部保持一個單例物件,所以不存在單例物件的新建釋放,僅僅是獲取。"
<< endl;
SingletonThreadSafeInstanceGetter<SingletonExampleOne>
sigSingletonInstanceGetter1(pscsOne);
SingletonExampleOne *pseSingleton1 = sigSingletonInstanceGetter1.GetInstance();
dw4 = GetTickCount();
for (int i = 0; i < 100000; ++i)
{
{
SingletonThreadSafeInstanceGetter<SingletonExampleOne>
sigSingletonInstanceGetter1(pscsOne);
SingletonExampleOne *pseSingleton11 = sigSingletonInstanceGetter1.GetInstance();
//do something
}
}
dw5 = GetTickCount();
for (int i = 0; i < 5; ++i)
phThread[i] =
(HANDLE)_beginthreadex(NULL, 0, &LoopFreeSingltonThread, pscsOne, 0, &threadID);
WaitForMultipleObjects(5, phThread, TRUE, INFINITE);
dw6 = GetTickCount();
for (int i = 0; i < 5; ++i)
CloseHandle(phThread[i]);
cout << "迴圈100000次僅獲取單例物件所用的時間為:" << dw5- dw4 << "毫秒" << endl;
cout << "5個執行緒,每個執行緒迴圈100000次僅獲取單例物件所用的時間為:" << dw6- dw5 <<
"毫秒" << endl;
cout << endl << "執行到這裡,說明在多執行緒獲取單例物件過程中,沒有發生過多執行緒衝突。" << endl;
char c;
cin >> c;
return 0;
}
在本人的機器上其中一次的執行結果如下
現在開始測試,可能用時比較長,請耐心等待...
迴圈100000次新建釋放單例物件所用的時間為:624毫秒
5個執行緒,每個執行緒迴圈100000次新建釋放單例物件所用的時間為:593毫秒
下面的測試,外部保持一個單例物件,所以不存在單例物件的新建釋放,僅僅是獲取。
迴圈100000次僅獲取單例物件所用的時間為:78毫秒
5個執行緒,每個執行緒迴圈100000次僅獲取單例物件所用的時間為:499毫秒
執行到這裡,說明在多執行緒獲取單例物件過程中,沒有發生過多執行緒衝突。
測試演示程式分為2大部分,每部分都是先在主執行緒中獲得十萬次單例類的例項,然後建立5個執行緒,每個執行緒也同樣迴圈獲取十萬次單例類的例項,主執行緒等待所有子執行緒結束,然後輸出某些資訊,在主執行緒和子執行緒中的for迴圈都加入了一對大括號用來控制單例類例項獲取器的生命週期,保證每次都把獲取器的例項釋放掉,使用這個方式來檢測建立和釋放物件所使用的時間,2部分的唯一區別就是第二部分在開始測試前,使用如下程式碼先獲取了一個單例類的例項
SingletonThreadSafeInstanceGetter<SingletonExampleOne> sigSingletonInstanceGetter1(pscsOne);
SingletonExampleOne *pseSingleton1 = sigSingletonInstanceGetter1.GetInstance();
這樣不管是主執行緒中的迴圈還是子執行緒中只是建立釋放例項獲取器類的例項,沒有真正建立釋放單例類的例項。
並在每一步都增加時間記錄,然後輸出每一步所花費的時間。
介紹了程式,下面我們介紹輸出的結果
如果讀者下載了測試例子,你的執行結果可能和我的不同,但是差不了太多,先來看看程式第一部分的結果,主執行緒迴圈100000次新建釋放單例物件所用的時間為:624毫秒,而5個執行緒,每個執行緒迴圈100000次新建釋放單例物件所用的時間為:593毫秒,這裡第二個值小於前一個的值,執行多次也可能大於,但是也大不了多少,肯定不會超過2倍,但是5個執行緒總共建立釋放了單例物件五十萬次,主執行緒只是十萬次,加上執行緒切換等額外開銷,所用時間應該大於主執行緒時間的五倍才對,那這裡是為什麼反而少了這麼多呢?其實道理也很簡單,主執行緒的十萬次是真實的十萬次,確實建立釋放單例物件十萬次,而當5個子執行緒工作時,由於其中一個執行緒建立好單例物件還沒有釋放的時候切換到了其他執行緒,其他執行緒再建立的時候其實根本就沒有建立,只是簡單的引用一下而已,當然速度快了很多,畢竟建立釋放物件才會耗費比較多的時間,而且這種情況發生的概率很高,所以時間耗費少了非常多,這樣的情況下就出現了執行緒五十萬次效率同十萬次接近的情況了。
對於第二大部分的例子,當保證一個單例類物件建立好不釋放,那麼這個主執行緒的for迴圈中就不會出現單例類例項的建立釋放,而是僅僅使用引用,所以其時間大幅減少,變成了僅僅78毫秒,但是5個執行緒還有499毫秒,同樣是引用,但是畢竟運行了五十萬次,並且還有執行緒切換,所以其時間是主執行緒十萬次時間的5倍還要多,並且由於沒有發生過真正的一次建立釋放動作,所以其時間應該小於第一部分中5個執行緒用的時間。
這裡還要注意一下例子中的中間部分的2行程式碼
SingletonThreadSafeInstanceGetter<SingletonExampleOne> sigSingletonInstanceGetter1(pscsOne);
SingletonExampleOne *pseSingleton1 = sigSingletonInstanceGetter1.GetInstance();
和開頭部分的2行程式碼
SingletonInstanceGetter<SingletonThreadLock<SingletonExampleOne>> sigOne;
SingletonThreadLock<SingletonExampleOne> *pscsOne = sigOne.GetInstance();
雖然都是主程式中的程式碼,但是臨界區物件pscsOne的生存期跟隨其獲取器是先於單例類SingletonExampleOne(生存期跟隨其獲取器例項sigSingletonInstanceGetter1)例項pseSingleton1建立的,釋放時由於程式碼先後順序,pscsOne也是晚於pseSingleton1釋放的,這樣是合理正確的,也就是單例類的生命週期必須在其對應的臨界區例項的生命週期內,晚於臨界區例項建立,早於臨界區例項釋放,不然就會出現問題,這裡一定要控制好。
相關推薦
C++中的單例模式及按需釋放模型(五)
四、多執行緒安全的通用單例類例項獲取器 例子工程的名稱是SingletonThreadSafeInstanceGetter。 剛開始寫本文時,本沒有想實現多執行緒版本,主觀上以為同通常的單例模式一樣,多個多執行緒同步就可以了,很簡單,讓讀者自己開發就好了,不過後來真正去思考
c++的單例模式及c++11對單例模式的優化
on() end per let namespace lease 是否 存在 建立 單例模式 單例模式,可以說設計模式中最常應用的一種模式了,據說也是面試官最喜歡的題目。但是如果沒有學過設計模式的人,可能不會想到要去應用單例模式,面對單例模式適用的情況,可能會優先考慮使用全
C++中單例物件的記憶體自動釋放
單例模式是一種在設計中很常用的模式,通過static函式建立一個物件,以後的所有的資料都通過該函式操作,保持資料唯一,用起來也很方便,但是有個小小的問題,就是單例物件的釋放問題,一般我們都是程式退出的時候統一釋放物件,但是這並不是特別完美,有時候你可能會忘記呼叫,然後就發生了記憶體洩露,當然,現代作業系統
Python設計模式中單例模式的實現及在Tornado中的應用
實例 類變量 attribute rap all wrap 線程 ++ 出現 單例模式的實現方式 將類實例綁定到類變量上 class Singleton(object): _instance = None def new(cls, *args): if not isinst
C++-----單例模式及案例
單例模式: 目的:為了讓類中只有一個例項,例項不需要自己釋放; 實現方法: 將 預設建構函式 和 拷貝建構函式 私有化; 內部維護一個 物件指標; 私有化唯一 指標; 對外提供 getInstance 方法來訪問這個指標; (此時外部已經沒有任何方法來修改並建立新的物
java 單例模式及在SSH框架中運用
定義: 確保某一個類只有一個例項,而且自動例項化並向整個系統提供這個例項。 程式碼: Singleton類稱為單例類,通過使用private的建構函式確保了在一個應用中只產生一個例項,並且是自行例項化的。 Java程式碼 /** * 執行緒安全的
C++實現單例模式(包括採用C++11中的智慧指標)
對於設計模式來說,以前只是看過基礎的理論,很多都沒有實現和使用過。這段時間看到了別人C++程式碼中使用了單例模式,發現了很多新的東西,特此總結記錄一下。說話比較囉嗦,希望由淺入深,幫助大家理解! 單例模式,顧名思義,即一個類只有一個例項物件。C++一般的方法
JAVA中的餓漢式和飽漢式單例模式及jdk中Runtime類的單例模式實現方式詳解
一、描述 單例模式是一種非常常見的設計模式,即一個類只能有一個物件(例項),一般通過將該類的構造器私有化,來阻止在該類外建立該類的物件,並提供給外界一個唯一的物件(這個物件在該類中建立)。 java中的單例模式常見的有兩種實現方式,一種是惡漢方式,即將該類物件
Java設計模式之單例模式及在Android中的重要使用
之前在開發中老用到一些設計模式可是呢又不是很懂,於是狠下心來琢磨一番。下面是我琢磨後總結的,希望對您有用。如果發現了問題,請幫忙指正。 一、單例模式是什麼? 單例模式最初的定義出現於《設計模式》:“保證一個類僅有一個例項,並提供一個訪問它的全域性
c++之單例模式
lsi 但是 desc 模式 單例模式 ron spl 希望 構造函數 1 本篇主要討論下多線程下的單例模式實現: 首先是 double check 實現方式: 這種模式可以滿足多線程環境下,只產生一個實例。 template<typename T>
【C#】單例模式<機房重構>
機房 .sh 不能 是否 gist 應用 調用方法 單例模式 sender 前言 在機房重構之前。我們學習了設計模式。在這次重構中,我們的任務就是將這些模式,加入到機房的重構中去。如今先來解決一個最簡單的問題——窗口的超生。 假設不加以限
單例模式及常見寫法分析(設計模式01)
啟動 nes 成員變量 額外 log 序列 spa tar adl 保證一個類僅有一個實例。並提供一個該實例的全局訪問點。 ——《設計模式》單例模式的概念非常easy。以下以C#語言為樣例,列出常見單例寫法的優缺點。1、簡單實現 public s
C#中單例的實現方法
inter sed .html thumb otto pri www ati code 本文實例講述了C#中單例的實現方法。分享給大家供大家參考。具體實現方法如下: 代碼如下: #region “實現這個窗口類的單例,單例類常用於被主窗口以show()方法打開的窗口
python之路_flask框架_單例模式及session原理
sql content pytho his pri 我們 main imp dbutil 實例化補充: 一、單例模式 1、單例模式介紹 單例模式(Singleton Pattern)是一種常用的軟件設計模式,該模式的主要目的是確保某一個類只有一個實例存在。當你希望在整
單例模式及搭建配置文件
height style asstream prope ssp sources 控制 input man 單例模式 //讀取配置文件的工具類-單例模式 public class ConfigManager { private static Propertie
7、【C++】單例模式/工廠模式
一、單例模式 單例模式,可以說設計模式中最常應用的一種模式了,據說也是面試官最喜歡的題目。但是如果沒有學過設計模式的人,可能不會想到要去應用單例模式,面對單例模式適用的情況,可能會優先考慮使用全域性或者靜態變數的方式,這樣比較簡單,也是沒學過設計模式的人所能想到的最簡單的方式了。
【C/C++】單例模式 Singleton
Backto C/C++ Index //.h class Singleton { public: static Singleton* instance(); static void Close(); private: Singleton(); ~Singleton
建立型:單例模式及相關應用
文章目錄 單例模式(Singleton) 優缺點 重點 懶漢式實現 執行緒不安全 synchronized關鍵字 雙重校驗鎖 靜態內部類 餓漢式實現 單例模式
python中單例模式的執行緒安全問題
看了好多文章都是java實現的,特此寫一篇python的。 這個問題的兩種解決方案: 1.最簡單粗暴的就是在系統中先生成一個單例,就不存線上程安全問題了 2.用雙重同步鎖去實現,一把鎖加外面,一把鎖加里面: class Singleton(object): __instance
【c++】單例模式
文章目錄 1.單例模式介紹 2.餓漢模式 1)簡單瞭解 2)優點:簡單 3)缺點:啟動時可能有負載導致啟動很慢 4)程式碼實現 3.懶漢模式 1)簡單瞭解