单例模式
保证一个类仅有一个实例,并提供一个该实例的全局访问点。
版本一
class A{
public :
static A *GetInstance(){
if(!_instance )
_instance = new A();
return _instance;
}
private:
A();
~A();
A(const A & a);
A& operator=(const A & a);
static A* _instance;
};
A *A::_instance = nullptr;
问题分析
- 没有实现对于_instance的析构函数,存在内存泄漏的问题
- 多线程下可能会造成重复new
版本二
class A{
public :
static A *GetInstance(){
if(_instance == nullptr)
{
_instance = new A();
atexist(Destructor) ;
}
return _instance;
}
private:
static void Destructor()
{
if(_instance != nullptr)
{
delete _instance ;
_instance = nullptr;
}
}
A();
~A();
A(const A & a);
A& operator=(const A & a);
static A* _instance;
};
A *A::_instance = nullptr;
问题分析
多线程下可能会造成重复new
版本三
#include <mutex>
class A{
public :
static A *GetInstance(){
if(_instance == nullptr)
{
std::lock_guard<std::mutex> lock(_mutex);
if(_instance == nullptr)
{
_instance = new A();
atexist(Destructor) ;
}
std::lock_guard<std::mutex> unlock(_mutex);
}
return _instance;
}
private:
static void Destructor()
{
if(_instance != nullptr)
{
delete _instance ;
_instance = nullptr;
}
}
A();
~A();
A(const A & a);
A& operator=(const A & a);
static A* _instance;
static std::mutex _mutex
};
A *A::_instance = nullptr;
std::mutex A::_mutex
问题分析
如果遇到cpu reorder的情况,就再一次异常了
方案四
cpu reorder
cpu运行时候为了加速,可能会将运行顺序进行一定程度的调整,单核下,这将是很强大的一向操作,但是多核协作时候,这是一个灾难。
为了解决cpu reorder造成影响,这里需要告知cpu,从这里的代码开始,你不准给我进行优化
代码
#include <mutex>
class A{
public :
static A *GetInstance(){
A *temp = _instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);
if(temp == nullptr)
{
std::lock_guard<std::mutex> lock(_mutex);
temp = _instance.load(std::memory_order_relaxed);
if(temp == nullptr)
{
_instance = new A();
std::atomic_thread_fence(std::memory_order_release);
atexist(Destructor) ;
}
std::lock_guard<std::mutex> unlock(_mutex);
_instance.save(std::memory_order_relaxed);
}
return _instance;
}
private:
static void Destructor()
{
if(_instance != nullptr)
{
delete _instance ;
_instance = nullptr;
}
}
A();
~A();
A(const A & a);
A& operator=(const A & a);
static A* _instance;
static std::mutex _mutex
};
A *A::_instance = nullptr;
std::mutex A::_mutex
版本五
class A{
public :
static A &GetInstance(){
static A instance;
return instance;
}
private:
A();
~A(){}
A(const A & a);
A& operator=(const A & a);
};
版本六
template <class T>
class A{
public :
static T &GetInstance(){
static T instance;
return instance;
}
protected:
A();
~A(){}
A(const A & a);
A& operator=(const A & a);
};
class B :public A<B>
{
friend class A<B>;
public:
~B();
private:
B(){};
B(const B& clone);
B& operator=(const B&);
}