C++多线程高并发,单例模式类的安全写法

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/qq_40666620/article/details/102613605
#include <iostream>
#include <mutex>
#include <thread>

std::mutex myMutex;
//call_once的标记
std::once_flag myFlag;


class MyClassA
{
private:
	static MyClassA* classAInstance;
	//禁止在外部通过此方法创建该类
	MyClassA() {};

public:
	static MyClassA* getInstance()
	{
		//双重判断,只会在第一次的时候进行执行,然后多个线程进去创建instance,
		//但是只能有一个抢到锁,创建完毕之后释放,其他的进来,instance已经不是NULL了
		//虽然初始化的时候会有可能很多线程进来创建instance,但是最终只能有一个instance完成实例化
		//并且之后使用的时候,第一个if就不为NULL了,也就不用进行锁的互斥了
		//然后getInstance()方法就是多线程安全且高效的了
		if (classAInstance == NULL)
		{
			std::unique_lock<std::mutex> myUniqueLock(myMutex);
			if (classAInstance == NULL)
			{
				classAInstance = new MyClassA();
				static finalReleaseReourcesClass releaseClass;
			}
		}
		return classAInstance;
	}

	//最终代码的方式释放资源,这是一个内部类
	//虽然说线程执行结束之后会自己释放内存,
	//使用内部类的目的就是在代码上就直接给他释放掉内存
	class finalReleaseReourcesClass
	{
	public:
		~finalReleaseReourcesClass()
		{
			if (MyClassA::classAInstance)
			{
				delete MyClassA::classAInstance;
				MyClassA::classAInstance = NULL;
			}
		}
	};

//下面的private是创建单例的方法,可以看到,这里没有双重保护,这也是把它设为
//private的原因之一,因为我们要在下面的public方法里面进行call_once的使用,
//效果上和双重判断是一样的
private:
	static void createInstance()
	{
		classAInstance = new MyClassA();
		std::cout << "thread "<<std::this_thread::get_id()<<"执行了createInstance" << std::endl;
		static finalReleaseReourcesClass releaseClass;
	}
public:
	static MyClassA* getInstance2()
	{
		//这里call_once的作用跟双重判断的作用一样,但是占用的资源更小,效率更高
		std::call_once(myFlag, createInstance);
		return classAInstance;
	}
};

//初始化实例为空
MyClassA* MyClassA::classAInstance = NULL;

//之所以写这个方法,就是为了让多个线程进行同时获取单例,这是线程的入口函数
void beginMyThread()
{
	std::cout << "thread " << std::this_thread::get_id() << " begin " << std::endl;
	MyClassA* ptr = MyClassA::getInstance2();
	std::cout << "thread " << std::this_thread::get_id() << " end " << std::endl;
}

int main()
{
	//MyClassA* myPtr1 = MyClassA::getInstance();
	//MyClassA* myPtr2 = MyClassA::getInstance();
	//MyClassA* myPtr3 = MyClassA::getInstance();
	//MyClassA* myPtr4 = MyClassA::getInstance();


	

	//单例设计模式数据共享问题


	//call_once():具备互斥量的能力,且比互斥量更加高效,需要用一个标记once_flag
	//第二个参数是一个函数名

	std::thread myThreadOne(beginMyThread);
	std::thread myThreadTwo(beginMyThread);
	myThreadOne.join();
	myThreadTwo.join();
}

猜你喜欢

转载自blog.csdn.net/qq_40666620/article/details/102613605