C++ 多线程(3):单例类 双重锁定

  • Post author:
  • Post category:其他




1.c++实现单例类,几点说明:



1)通过私有化构造函数使你不能自由创建对象

(2)只能通过GetInstance得到一个实例(对象)

(3)而且可以看出只要创建了第一次以后再调用此方法就返回第一次创建的对象的指针,故曰:单例类

(4)通过类中类来析构创建的对象,不能直接用Model类的析构函数来析构

(5)其中也利用了静态变量的生存周期是整个源程序这一点,静态私有成员变量与静态公共成员变量的区别跟静态没关系就是私有与公共的区别。在私有下,静态成员变量即不能通过类直接访问也不能通过对象直接访问

class Model {
private:
	Model() {};
private:
	static Model* p_model;
public:
	static Model* GetInstance()
	{
		if (!p_model)
		{
			p_model = new Model();
			static ModelDestructor ml;
		}
		return p_model;
	}
	class ModelDestructor{
	public:
		~ModelDestructor()
		{
			if (!p_model)
			{
				delete p_model;
				p_model = nullptr;
			}
		}
	};
	void test()
	{
		std::cout << "This is a test" << std::endl;
	}
};
Model* Model::p_model = nullptr;


2.多个线程同时创建单例类:


(1)当两个或两个以上的线程同时执行GetInstance的时候,肯定有一个线程拿到锁并把Model对象创建好了,故这个首线程退出后,其它的线程再进入也无法再创建新的对象了

(2)存在的问题是首线程之外的线程明明没有了创建对象的权利还天天的去拿锁,造成资源的浪费。

class Model {
private:
	Model() {};
private:
	static Model* p_model;
	static std::mutex mutex_p_model;
public:
	static Model* GetInstance()
	{
		std::unique_lock<std::mutex> p_model_guard(mutex_p_model);
		if (!p_model)
		{
			p_model = new Model();
			static ModelDestructor ml;
		}
		return p_model;
	}
	class ModelDestructor{
	public:
		~ModelDestructor()
		{
			if (!p_model)
			{
				delete p_model;
				p_model = nullptr;
			}
		}
	};
	void test()
	{
		std::cout << "This is a test" << std::endl;
	}
};
void mythread()
{
	std::cout << std::this_thread::get_id() << "开始工作" << std::endl;
	Model* p = Model::GetInstance();
	std::cout << std::this_thread::get_id() << "工作完成" << std::endl;
}
Model* Model::p_model = nullptr;
std::mutex Model::mutex_p_model = {};
int main()
{
	std::thread thread1(mythread);
	std::thread thread2(mythread);
	thread1.join();
	thread2.join();
	std::cout << "Done!" << std::endl;
}


3.为解决上述问题引入双重锁定,如下:


(1)所谓的双重锁定只不过是在上锁之前也进行一下检查,如果说你连拿到锁的资格都没有你凭啥去创建对象,死去吧你

class Model {
private:
	Model() {};
private:
	static Model* p_model;
	static std::mutex mutex_p_model;
public:
	static Model* GetInstance()
	{
		if (!p_model)
		{
			std::unique_lock<std::mutex> p_model_guard(mutex_p_model);
			if (!p_model)
			{
				p_model = new Model();
				static ModelDestructor ml;
			}
		}
		return p_model;
	}
	class ModelDestructor{
	public:
		~ModelDestructor()
		{
			if (!p_model)
			{
				delete p_model;
				p_model = nullptr;
			}
		}
	};
	void test()
	{
		std::cout << "This is a test" << std::endl;
	}
};
void mythread()
{
	std::cout << std::this_thread::get_id() << "开始工作" << std::endl;
	Model* p = Model::GetInstance();
	std::cout << std::this_thread::get_id() << "工作完成" << std::endl;
}
Model* Model::p_model = nullptr;
std::mutex Model::mutex_p_model = {};
int main()
{
	std::thread thread1(mythread);
	std::thread thread2(mythread);
	thread1.join();
	thread2.join();
	std::cout << "Done!" << std::endl;
}

4.结论:

何必呢?在创建多个线程之前把对象创建好不就行了,md



版权声明:本文为weixin_44142774原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。