单例模式介绍与例子
单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例
例子如下:
using namespace std;
class single
{
private:
single() {}
private:
static single * instance;
public:
static single* Getinstance()
{
if (instance = nullptr)
{
instance = new single();
static CG cg;
}
return instance;
}
class CG //用来回收对象
{
public:
~CG()
{
if (single::instance)
{
delete single::instance;
single::instance = nullptr;
}
}
};
void test()
{
cout << "测试" << endl;
}
};
single *single::instance = nullptr;
int main()
{
single * s = single::Getinstance();
s->test();
single::Getinstance()->test();
}
单例模式共享数据分析与问题解决
第一个问题:除了主线程外,我们可以还需要在其他线程中创建single这个单例类的对象,这就涉及到了互斥。
比如
void func()
{
cout << "线程开始了,线程ID为: " << this_thread::get_id() << endl;
single * s = single::Getinstance();
cout << "线程结束,线程ID为:" << this_thread::get_id() << endl;
}
single *single::instance = nullptr;
int main()
{
thread t(func);
thread t1(func);
t.join();
t1.join();
return 0;
}
解决办法:使用双重锁定
static single* Getinstance()
{
if (instance == nullptr)//双重锁定,因为if(instance == nullptr)不代表instance一定没被new
{
unique_lock<mutex>lock(mymutex);//加锁
if (instance == nullptr)
{
instance = new single();
static CG cg;
}
}
return instance;
}
std::call_once()
头文件<mutex>
C++11引入的函数,该函数的第二个参数是一个可调用对象,它的作用是保证该对象只调用一次.具备互斥能力,而且 性能更好。
需要和标记结合使用,这个标记是std::once_flag
工作原理:
call_once使用标记来确定对应的调用对象是否执行,调用call_once成功后,call_once就把这个标记设置为已调用状态,下次对应的对象就不会在执行了.
可以看到里面有一个void*成员初始化的时候设置为nullptr,当使用了一次这个指针就不是nullptr,通过判断是否为nullptr来推测出是否已经调用.
mutex mymutex;
once_flag flag;
class single
{
private:
single() {}
private:
static void CreateInstance()//只被调用一次
{
cout << "CreateInstance执行了!" << endl;
instance = new single();
static CG cg;
}
static single * instance;
public:
static single* Getinstance()
{
call_once(flag, CreateInstance);
return instance;
}
class CG //用来回收对象
{
public:
~CG()
{
if (single::instance)
{
delete single::instance;
single::instance = nullptr;
}
}
};
void test()
{
cout << "测试" << endl;
}
};
void func()
{
cout << "线程开始了,线程ID为: " << this_thread::get_id() << endl;
single * s = single::Getinstance();
cout << "线程结束,线程ID为:" << this_thread::get_id() << endl;
}
single *single::instance = nullptr;
int main()
{
thread t(func);
thread t1(func);
t.join();
t1.join();
return 0;
}