单例模式需要注意的问题点

本文探讨了C++中单例模式的多种实现方式,包括潜在的问题和解决方案。从版本一开始,指出没有析构函数导致的内存泄漏,到版本二引入析构函数但依然存在多线程问题,再到版本三通过互斥锁解决线程安全,然后分析了版本四如何应对CPU重排序带来的影响,最后展示了更简洁的版本五和模板化的版本六。这些实现展示了单例模式在多线程环境下的演进和优化。
摘要由CSDN通过智能技术生成

单例模式

保证一个类仅有一个实例,并提供一个该实例的全局访问点。

版本一

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;

问题分析

  1. 没有实现对于_instance的析构函数,存在内存泄漏的问题
  2. 多线程下可能会造成重复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&);
		
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值