C++单例模式实例——如何管理内存及线程安全(代码)
前言
单例模式是设计模式中比较简单的一种模式,也是实际使用中比较常用的一种。比如可以用单例模式来管理一些全局信息。对于单例模式中的内存管理,大致有三种做法:
- 直接交由系统,程序退出时自动释放内存
- 手动 delete
- 自动 delete
其中第三种做法比较巧妙。
关于线程安全,下面代码是使用 unique_lock 自动管理 mutex,还用一种方法是使用 std::call_once()。
代码
下面的代码给出了第二种和第三种方法的实现。
sp.hpp
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;
std::mutex instance_mutex;
class SP{
private:
SP(){}
static SP *m_pInstance; //static使得 m_pInstance 的作用域到程序结束
class FREE{ //这个class专门负责 delete
public:
~FREE()
{
if(SP::m_pInstance)
{
delete SP::m_pInstance;
SP::m_pInstance = NULL;
}
}
};
public:
static SP* GetInstance() //static 是关键,否则无法直接调用
{
if(m_pInstance == NULL) //双重锁定,提高运行效率,减少不必要的lock,unlock
{
std::unique_lock<std::mutex> mutex1(instance_mutex); //c++ 11,自动lock,unlock
if(!m_pInstance)
{
m_pInstance = new SP();
static FREE f; //static 表示作用域直到程序推出,也就是说程序退出时会调用析构函数,从而达到自动释放内存的作用
}
}
return m_pInstance;
}
static void Free() //手动 delete
{
if(m_pInstance)
{
delete m_pInstance;
m_pInstance = NULL;
}
}
};
// 以下对于静态成员的初始化最好放到 cpp 中
// 这里作为测试为了方便就放在 hpp 中了
SP* SP::m_pInstance = NULL;
调用的代码如下
SP *p1 = SP::GetInstance();
SP *p2 = SP::GetInstance();
SP::Free();
SP::Free();
p1->Free();
p2->Free();