剑指offer_Q02单例模式

单例模式

单例模式解析

动机/需求来源

面像对象解决了“抽象”的问题,但是有时会有一些性能损失。

需要保证在系统中只存在一个实例,保证逻辑正确和较好的效率。

绕过常规构造器,提供只能生成一个实例的机制,承担类设计者的责任。

设计要点

  • 构造函数和拷贝构造函数都是私有private
  • 静态变量,指向自身的指针
  • 静态函数,获取instance
  • 线程安全和线程非安全
  • 多线程环境下:双检查锁
  • 内存reorder下双检查锁的失效(待阅读整理!)

C#下的单例模式

C#知识点

  • 静态构造函数:第一次被使用之前自动调用,且保证只调用一次。

  • struct 和 class,未指定时,默认都是private。

  • 静态构造函数先初始化静态变量,再执行函数体内语句。再执行普通构造函数,构造函数先初始化成员变量,再执行函数体内语句。

  • 待增加具体的实现方法

C++下的单例模式

class MySingleton
{
public:
	static MySingleton* getInstanceSingleThread();   //非线程安全版本,仅适用于单线程
	static MySingleton* getInstanceMultiThreadSlow(); //单纯加锁,安全但是效率低
	static MySingleton* getInstanceMultiThreadEfficient(); //双重检查加锁 DCLP,存在内存reorder 的风险
	static MySingleton* getInstanceMultiThreadEfficientAndSafe(); //安全的多线程版本

	static MySingleton* mInstance;

private:
	MySingleton() { cout << "singleton constructor."<<endl; } //私有构造函数
	MySingleton(const MySingleton& obj) { cout << "singleton copy constructor" << endl; } //私有拷贝构造
};

非线程安全版本

inline MySingleton* MySingleton::getInstanceSingleThread()
{
	if (mInstance==nullptr)
	{
		mInstance = new MySingleton();
	}
	return mInstance;
}

单纯加锁,安全但效率低

inline MySingleton * MySingleton::getInstanceMultiThreadSlow()
{
	//Lock lock;
	if (mInstance == nullptr)
	{
		mInstance = new MySingleton();
	}
	return mInstance;
}

双重检查,DCLP,但存在内存reorder风险

inline MySingleton * MySingleton::getInstanceMultiThreadEfficient()
{
	if (mInstance == nullptr)
	{
		//Lock lock;
		if (mInstance == nullptr)
		{
			mInstance = new MySingleton();  //1分配内存、2执行构造函数、3传回地址给指针; 是假想的顺序。但是,编译器有可能将该顺序给优化了
		}   //如果1分配内存之后直接传回地址给指针,此时另一个线程判断mInstance不为空,就拿去用,会内存出错(因未初始化)。
	}
	return mInstance;
}

安全的多线程方法

//https://www.bilibili.com/video/av24176315?p=12
std::atomic<MySingleton*> MySingleton::mInstance;
std::mutex MySingleton::m_mutex;
inline MySingleton * MySingleton::getInstanceMultiThreadEfficientAndSafe()
{
	MySingleton* tmp = mInstance.load(std::memory_order_relaxed);
	std::atomic_thread_fence(std::memory_order_acquire);
	if (tmp == nullptr)
	{
		std::lock_guard<std::mutex> lock(m_mutex);
		tmp = mInstance.load(std::memory_order_relaxed);
		if (tmp == nullptr)
		{
			tmp = new MySingleton;
			std::atomic_thread_fence(std::memory_order_release);
			mInstance.store(tmp, std::memory_order_relaxed);
		}
	}
	return tmp;
}

tomic_thread_fence(std::memory_order_release);
mInstance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}


发布了48 篇原创文章 · 获赞 10 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/mhywoniu/article/details/104885399