C++單例懶漢式和多執行緒問題(MUTEX 保護)
單例懶漢式和多執行緒問題
作為單例模式,是在整個程式執行期間只會建立一份記憶體空間,為了達到這個目標
1、需要將建構函式設定為私有成員
2、需要一個私有的靜態指標指向自身
3、需要一個公有的靜態函式將這個上面的靜態指標露出來
如下的程式碼就是一個懶漢式的單例
但是上面的程式碼有明顯的問題,就是遇到多執行緒的情況下,因為多個執行緒如果同事建立記憶體,由於彼此之間
並不能及時檢查到記憶體已經分配,會分配多個記憶體,這個時候我們至少需要一個執行緒間同步手段來讓他們之間
序列的執行,這個時候就涉及到兩次檢查(double check)
如果沒有mutex保護就是下面這個程式:
會跑出結果
con begin
con begin
con begin
con end
a:10
b:20
1
0x7fc3880008c0
con end
a:10
b:20
2
0x7fc3800008c0
con end
a:10
b:20
3
0x7fc3840008c0
可以看到
0x7fc3880008c0 0x7fc3800008c0 0x7fc3840008c0
明顯是3個不同的記憶體空間 這就不對了,而且可以看到建構函式
呼叫了3次
為此我們使用mutex來保護臨時
如下:
static single_ins* setp() //函式獲得指標值賦給靜態成員指標變數
39 {
40 //懶漢式
41 if(myc == NULL)
42 {
43 pthread_mutex_lock(&counter_mutex); //mutex 保護臨界區
44 if(myc == NULL) //兩次檢查
45 {
46 myc = new single_ins;
47 cnt++;
48 }
49 pthread_mutex_unlock(&counter_mutex); //mutex結束
50 }
這樣程式碼如下:
跑出的結果如下:
con begin
con end
a:10a:10
b:20
1
0x7f21f40008c0
b:20
1
0x7f21f40008c0
a:10
b:20
1
0x7f21f40008c0
現在就是正常的了。所以懶漢試單例遇到多執行緒一定要注意,餓漢試沒有問題。
當然這是一個小列子而已,執行緒安全是一個很大的話題,特別需要注意。
作者微信:
作為單例模式,是在整個程式執行期間只會建立一份記憶體空間,為了達到這個目標
1、需要將建構函式設定為私有成員
2、需要一個私有的靜態指標指向自身
3、需要一個公有的靜態函式將這個上面的靜態指標露出來
如下的程式碼就是一個懶漢式的單例
點選(此處)摺疊或開啟
-
#include<iostream>
-
using namespace std;
-
-
class single_ins
-
{
-
private:
-
int a;
-
int b;
-
single_ins()
-
{
-
a= 0;
-
b= 0;
-
}
-
static single_ins* myc;
-
public:
-
void setval(const int& a,const int& b)
-
{
-
this->a = a;
-
this->b = b;
-
}
-
-
void print()
-
{
-
cout<<"a:"<<a<<endl;
-
cout<<"b:"<<b<<endl;
-
}
-
-
-
static single_ins* setp()
-
{
-
//?
-
if(myc == NULL)
-
{
-
myc = new single_ins;
-
}
-
//?
-
return myc;
-
}
-
-
static void pfree()
-
{
-
if(myc != NULL)
-
{
-
delete myc;
-
myc = NULL;
-
}
-
}
-
-
};
-
-
//? init static value
-
single_ins* single_ins::myc = NULL;
-
//nit static value
-
//single_ins* single_ins::myc = new single_ins;
-
-
int main()
-
{
-
single_ins* a = single_ins::setp();
-
single_ins* b = single_ins::setp();
-
a->setval(10,20);
-
b->print();
-
-
cout<<a<<" "<<b<<endl;
-
single_ins::pfree();
-
- }
並不能及時檢查到記憶體已經分配,會分配多個記憶體,這個時候我們至少需要一個執行緒間同步手段來讓他們之間
序列的執行,這個時候就涉及到兩次檢查(double check)
如果沒有mutex保護就是下面這個程式:
點選(此處)摺疊或開啟
-
#include <iostream>
-
#include <unistd.h>
-
using namespace std;
-
-
-
//單列模式
-
class single_ins
-
{
-
private:
-
int a;
-
int b;
-
single_ins()
-
{
-
cout<<"con begin\n";
-
a= 0;
-
b= 0;
-
sleep(10); //故意拖長建構函式執行時間,造成懶漢式多執行緒問題
-
cout<<"con end\n";
-
}
-
static single_ins* myc;//單例需要一個靜態指標
-
static int cnt;//構造呼叫次數統計
-
public:
-
void setval(const int& a,const int& b)
-
{
-
this->a = a;
-
this->b = b;
-
}
-
-
void print()
-
{
-
cout<<"a:"<<a<<endl;
-
cout<<"b:"<<b<<endl;
-
cout<<cnt<<endl;
-
}
-
-
-
static single_ins* setp() //函式獲得指標值賦給靜態成員指標變數
-
{
-
//懶漢式
-
if(myc == NULL)
-
{
-
myc = new single_ins;
-
cnt++;
-
}
-
//懶漢式
-
return myc;
-
}
-
static void pfree()
-
{
-
if(myc != NULL)
-
{
-
delete myc;
-
myc = NULL;
-
}
-
}
-
};
-
-
//懶漢式 init static value
-
single_ins* single_ins::myc = NULL;
-
int single_ins::cnt = 0;
-
//餓漢試 init static value
-
//single_ins* single_ins::myc = new single_ins;
-
/*
-
懶漢式的問題在於多執行緒呼叫的時候會出現問題,很可能同時建立出多個記憶體空間,
-
而不是單列了。
- */
-
void* main21(void* argc)
-
{
-
single_ins* inp = (single_ins*)argc;
-
-
inp = single_ins::setp();
-
inp->setval(10,20);
-
inp->print();
-
cout<<inp<<"\n";
-
return NULL;
-
}
-
-
-
int main(void)
-
{
-
pthread_t tid;
-
single_ins* a[3] = {NULL};
-
void* tret[3] = {NULL};
-
for(int i = 0 ; i<3; i++)
-
{
-
pthread_create(&tid,NULL,main21,(void*)a[i]);
-
//pthread_join(tid, &(tret[i]));
-
}
-
sleep(50);
-
single_ins::pfree();
-
- }
con begin
con begin
con begin
con end
a:10
b:20
1
0x7fc3880008c0
con end
a:10
b:20
2
0x7fc3800008c0
con end
a:10
b:20
3
0x7fc3840008c0
可以看到
0x7fc3880008c0 0x7fc3800008c0 0x7fc3840008c0
明顯是3個不同的記憶體空間 這就不對了,而且可以看到建構函式
呼叫了3次
為此我們使用mutex來保護臨時
如下:
static single_ins* setp() //函式獲得指標值賦給靜態成員指標變數
39 {
40 //懶漢式
41 if(myc == NULL)
42 {
43 pthread_mutex_lock(&counter_mutex); //mutex 保護臨界區
44 if(myc == NULL) //兩次檢查
45 {
46 myc = new single_ins;
47 cnt++;
48 }
49 pthread_mutex_unlock(&counter_mutex); //mutex結束
50 }
這樣程式碼如下:
點選(此處)摺疊或開啟
-
#include <iostream>
-
#include <unistd.h>
-
using namespace std;
-
-
pthread_mutex_t counter_mutex = PTHREAD_MUTEX_INITIALIZER;
-
-
//單列模式
-
class single_ins
-
{
-
private:
-
int a;
-
int b;
-
single_ins()
-
{
-
cout<<"con begin\n";
-
a= 0;
-
b= 0;
-
sleep(10); //故意拖長建構函式執行時間,造成懶漢式多執行緒問題
-
cout<<"con end\n";
-
}
-
static single_ins* myc;//單例需要一個靜態指標
-
static int cnt;//構造呼叫次數統計
-
public:
-
void setval(const int& a,const int& b)
-
{
-
this->a = a;
-
this->b = b;
-
}
-
-
void print()
-
{
-
cout<<"a:"<<a<<endl;
-
cout<<"b:"<<b<<endl;
-
cout<<cnt<<endl;
-
}
-
-
-
static single_ins* setp() //函式獲得指標值賦給靜態成員指標變數
-
{
-
//懶漢式
-
if(myc == NULL)
-
{
-
pthread_mutex_lock(&counter_mutex); //mutex 保護臨界區
-
if(myc == NULL) //兩次檢查
-
{
-
myc = new single_ins;
-
cnt++;
-
}
-
pthread_mutex_unlock(&counter_mutex); //mutex結束
-
}
-
//懶漢式
-
return myc;
-
}
-
static void pfree()
-
{
-
if(myc != NULL)
-
{
-
delete myc;
-
myc = NULL;
-
}
-
}
-
};
-
-
//懶漢式 init static value
-
single_ins* single_ins::myc = NULL;
-
int single_ins::cnt = 0;
-
//餓漢試 init static value
-
//single_ins* single_ins::myc = new single_ins;
-
/*
-
懶漢式的問題在於多執行緒呼叫的時候會出現問題,很可能同時建立出多個記憶體空間,
-
而不是單列了。
-
*/
-
-
-
-
void* main21(void* argc)
-
{
-
single_ins* inp = (single_ins*)argc;
-
-
inp = single_ins::setp();
-
inp->setval(10,20);
-
inp->print();
-
cout<<inp<<"\n";
-
return NULL;
-
}
-
-
-
int main(void)
-
{
-
pthread_t tid;
-
single_ins* a[3] = {NULL};
-
void* tret[3] = {NULL};
-
for(int i = 0 ; i<3; i++)
-
{
-
pthread_create(&tid,NULL,main21,(void*)a[i]);
-
//pthread_join(tid, &(tret[i]));
-
}
-
sleep(50);
-
single_ins::pfree();
-
- }
con begin
con end
a:10a:10
b:20
1
0x7f21f40008c0
b:20
1
0x7f21f40008c0
a:10
b:20
1
0x7f21f40008c0
現在就是正常的了。所以懶漢試單例遇到多執行緒一定要注意,餓漢試沒有問題。
當然這是一個小列子而已,執行緒安全是一個很大的話題,特別需要注意。
作者微信:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2136964/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 設計模式-單例模式之懶漢式-多執行緒設計模式單例執行緒
- (單例設計模式中)懶漢式與餓漢式在多執行緒中的不同單例設計模式執行緒
- C#單例—餓漢式和懶漢式C#單例
- 設計模式-單例模式之餓漢式-多執行緒設計模式單例執行緒
- java單例模式懶漢和餓漢Java單例模式
- java 多執行緒 程式保護Java執行緒
- 設計模式:單例模式 (關於餓漢式和懶漢式)設計模式單例
- 設計模式——懶漢式單例類PK餓漢式單例類設計模式單例
- 餓漢式單例與懶漢式單例的C#實現單例C#
- 詳談單例、餓漢、和懶漢模式單例模式
- scala:分別使用懶漢式和餓漢式實現單例模式單例模式
- C++ 多執行緒框架 (2):Mutex 互斥和 Sem 訊號量C++執行緒框架Mutex
- 多執行緒(2)-執行緒同步互斥鎖Mutex執行緒Mutex
- 【java】單例設計模式——餓漢式和懶漢式、Runtime、TimerJava單例設計模式
- 單例模式執行緒安全reorder問題單例模式執行緒
- 多執行緒問題執行緒
- 多執行緒下的單例執行緒單例
- VC多執行緒 C++ 多執行緒執行緒C++
- java多執行緒執行問題Java執行緒
- java 多執行緒守護執行緒Java執行緒
- Java多執行緒——守護執行緒Java執行緒
- 企圖使用c++執行緒解決nodejs單執行緒問題C++執行緒NodeJS
- JAVA_多執行緒_單例模式Java執行緒單例模式
- C++ 執行緒安全的單例模式C++執行緒單例模式
- 多執行緒-執行緒控制之守護執行緒執行緒
- 利用C++多執行緒優化n王后問題C++執行緒優化
- 問一個守護執行緒問題?執行緒
- 純Mutex實現多執行緒交替列印Mutex執行緒
- Java多執行緒面試高配問題---多執行緒(3)🧵Java執行緒面試
- java synchronized 保護執行緒安全Javasynchronized執行緒
- 【多執行緒】常見問題簡單總結執行緒
- Java多執行緒和併發問題集Java執行緒
- 多執行緒-死鎖問題概述和使用執行緒
- 瀏覽器多執行緒和js單執行緒瀏覽器執行緒JS
- C++ 多執行緒C++執行緒
- c++多執行緒C++執行緒
- 多執行緒問題解釋執行緒
- 多執行緒相關問題執行緒