/*
1、为什么不能在单例类的析构函数中进行delete
2、析构函数是在对象释放的时候才会执行的,就是说要手动delete才会窒息你个析构函数
3、当我们手动执行delete后,这时m_instance已经不存在了
4、如果在析构函数中执行delete m_instance,相当于delete了两次
*/
class MyCAS
{
private:
MyCAS() {} //私有化构造函数
private:
static MyCAS* m_instance; //静态成员变量
public:
static MyCAS *GetInstance()
{
if (m_instance == NULL)
{
m_instance = new MyCAS();
static CGarhuishou cl; //程序退出的时候,会自动调用c1析构函数
}
return m_instance;
}
void func()
{
cout << "test" << endl;
}
class CGarhuishou //类中套类,用来释放对象
{
public:
~CGarhuishou()
{
if (MyCAS::m_instance)
{
delete MyCAS::m_instance;
MyCAS::m_instance = NULL;
}
}
};
};
//静态变量初始化
MyCAS* MyCAS:: m_instance = NULL;
int main()
{
MyCAS* p_a = MyCAS::GetInstance();
//MyCAS* p_a = MyCAS::GetInstance(); //第二次调用 直接返回m_instance
return 0;
}
上面代码是在主线程中创建的单例,没有任何问题;但是如果在多个子线程中创建单例,就有可能出现new 多个 m_instance了
void mythread()
{
cout << "我的线程开始执行了" << endl;
MyCAS* p_a = MyCAS::GetInstance();
cout << "我的线程执行完毕了" << endl;
}
int main()
{
//两个线程创建单例,就科能出现问题,可能都new 了 m_instance
thread myobj1(mythread);
thread myobj2(mythread);
myobj1.join();
myobj2.join();
return 0;
}
在创建线程的时候,加互斥量能否解决这个问题呢? 确实可以解决
但是这样效率会很低,因为每次都要进入互斥量等待
mutex my_mutex;
static MyCAS *GetInstance()
{
unique_lock<mutex> unilock(my_mutex);
//my_mutex.lock();
if (m_instance == NULL)
{
m_instance = new MyCAS();
static CGarhuishou cl; //程序退出的时候,会自动调用c1析构函数
}
//my_mutex.unlock();
return m_instance;
}
再加一次 if (m_instance == NULL) 可以起到 双重检查的左右,后续创建的时候,根据m_instance 可以是否进入锁等待状态
call_once
c++引入的函数,该函数的第二个参数是一个函数名a()
call_once功能是能够保证函数a()只被调用一次
call_once具备互斥量这种能力,而且效率上,比互斥量消耗的更少
once_flag flag;
public:
static void CreateInstance() //只被调用一次
{
m_instance = new MyCAS();
static CGarhuishou cl;
}
static MyCAS *GetInstance()
{
call_once(flag, CreateInstance);
return m_instance;
}