单例模式
整个项目中有某个或者某些特殊类 只能创建一个对象 不能创建多个
单例类
class A
{
private:
A() {};//直接将构造函数私有化 这样就不能通过A a = new A;来实现对类对象的创建
private:
static A* m_instance;//这个静态类对象就是我们能创建的那个唯一的一个类对象 设置为静态就是改变对象的作用于 归属于整个类
public:
/*这个函数就是用来创建唯一的一个类对象*/
static A* getInstance()
{
if (m_instance == NULL)
{
m_instance = new A();
static GarColl GC;//当程序退出的时候就会调用这个对象的析构函数 自然就会把m_instance对象删除掉
}
return m_instance;
}
/*类中的类 用来对A::m_instance进行释放*/
class GarColl
{
public:
~GarColl()
{
if (A::m_instance != NULL)
{
delete A::m_instance;
A::m_instance = NULL;
}
}
};
};
A* A::m_instance = NULL;//类中的静态变量就需要在类外先初始化 但是这个是私有对象 可以这样初始化吗
int main()
{
A *a = A::getInstance();//这样就创建了
A *b = A::getInstance();//其实是一个指针对象 存储的是同一个地址
cout<<"a:"<<a<<endl;//a:00000127D6C73320
cout<<"b:"<<b<<endl;//b:00000127D6C73320
return 0;
}
单例设计模式会面临的问题(双重锁定解决办法)
在线程中创建单例类对象 此时就需要对get_instance()进行互斥
因为如果不做互斥就会导致 如果两个线程依次越过了m_instance == NULL判断就会导致对m_instance静态对象new了两次 其中一个线程获取的地址肯定就错误了
很明显 在创建之前加一个锁就行了
static A* getInstance()
{
std::unique_lock<std::mutex>uniqueTex(mtex);//进行一个加锁
if (m_instance == NULL)
{
//std::unique_lock<std::mutex>uniqueTex(mtex);//如果在这里加锁没有意义 同样会new两次
m_instance = new A();
static GarColl GC;//当程序退出的时候就会调用这个对象的析构函数 自然就会把m_instance对象删除掉
}
return m_instance;
}
但是这样你就会发现 本来我们只需要在线程每次初始化的时候加个锁就行了 但是现在只要执行了这个函数就会加锁解锁一次 效率很低
解决办法:双重锁定
static A* getInstance()
{
if (m_instance == NULL)
{
std::unique_lock<std::mutex>uniqueTex(mtex);//这样就可以了
if (m_instance == NULL)
{
m_instance = new A();
static GarColl GC;//当程序退出的时候就会调用这个对象的析构函数 自然就会把m_instance对象删除掉
}
}
return m_instance;
}
std::call_once
call_once能保证函数在程序中只被调用一次 在效率上比互斥量更高消耗资源更少
如果call_once包含的函数被调用 则定义的std::once_flag标记则会被设置为已调用 此时这个被包含的函数就不能再被调用
std::once_flag
是一个结构 系统定义的标记
std::once_flag g_flag;
void fun()
{
}
void start()
{
std::call_once(g_flag,fun);
}
int main()
{
thread mobj1(start);
}