这篇文章主要为大家展示了“C++如何解决单例懒汉式和多线程问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“C++如何解决单例懒汉式和多线程问题”这篇文章吧。
单例懒汉式和多线程问题
作为单例模式,是在整个程序运行期间只会建立一份内存空间,为了达到这个目标
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
现在就是正常的了。所以懒汉试单例遇到多线程一定要注意,饿汉试没有问题。
当然这是一个小列子而已,线程安全是一个很大的话题,特别需要注意。
以上是“C++如何解决单例懒汉式和多线程问题”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。