C++11单例设计模式共享数据分析

x33g5p2x  于2022-03-06 转载在 其他  
字(3.9k)|赞(0)|评价(0)|浏览(584)

1.设计模式大概谈

“设计模式”:代码的一些写法(这些写法跟常规写法不怎么一样):程序灵活,维护起来可能很方便,但是别人接管、阅读代码都会很痛苦。

用“设计模式”理念写出的代码很晦涩的。《head first》讲设计模式,可以了解一下。

老外为应付特别大的项目的时候,把项目的开发经验、模块划分经验,总结整理成设计模式(先有开发需求,后又理论总结和整理)

设计模式拿到中国来,不太一样,拿着一个程序(项目)往设计模式上套,一个小小的项目它非要弄几个设计模式进去,本末倒置。

设计模式肯定有它独特的优点,要活学活用,不要深陷其中,生搬硬套;

2.单例设计模式

单例设计模式,使用的频率比较高;

单例:整个项目中,某个或者某些特殊的类,属于该类的对象,只能创建一个,多了创建不了;

单例类;实例代码如下:

#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>
#include<mutex>

using namespace std;

class MyCAS
{
private:
	MyCAS(){} //私有化了的构造函数

private:
	static MyCAS *m_instance; //静态成员变量

public:
	static MyCAS *GetInstance()
	{
		if (m_instance == NULL)
		{
			m_instance == new MyCAS();
			static CGarhuishou cl;
		}
		return m_instance;
	}

	class CGarhuishou //类中套类,用来释放对象
	{
	public:
		~CGarhuishou() //类的析构函数中
		{
			if (MyCAS::m_instance)
			{
				delete MyCAS::m_instance;
				MyCAS::m_instance = NULL;
			}
		}
	};

	void func()
	{
		cout << "测试" << endl;
	}
};

//类静态变量初始化
MyCAS  *MyCAS::m_instance = NULL;

int main()
{
	MyCAS *p_a = MyCAS::GetInstance(); //创建一个对象,返回该类(MyCAS)对象的指针
	p_a->func();
	MyCAS::GetInstance()->func();  //该装载的数据装载

	return 0;
}

3.单例设计模式共享数据分析、解决

理想情况下,主线程中单例类对象初始化,加载数据。

现实面临的问题:需要在我们自己创建的线程(不是主线程)中来创建MyCAS这个单例类的对象,这种线程可能不止一个(最少两个 )

我们可能面临GetInstance()这种成员函数要互斥;

虽然这两个线程 是同一个入口函数,但是千万要记住,这是两个线程,所以这里会有两个流程同时开始执行mythread!实例代码如下:

#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>
#include<mutex>

using namespace std;

std::mutex resource_mutex;

class MyCAS
{
private:
	MyCAS() {} //私有化了的构造函数

private:
	static MyCAS *m_instance; //静态成员变量

public:
	static MyCAS *GetInstance()
	{
		//提高效率
		//a)如果if (m_instance != NULL) 条件成立,则肯定表示m_instance已经被new过了;
		//b)如果if (m_instance == NULL),不代表m_instance一定没被new过;

		if (m_instance == NULL) //双重锁定(双程检查)
		{ 
			std::unique_lock<std::mutex> mymutex(resource_mutex); //自动加锁,但效率非常低
			if (m_instance == NULL)
			{
				m_instance == new MyCAS();
				static CGarhuishou cl;
			}
		}
		return m_instance;
	}

	class CGarhuishou //类中套类,用来释放对象
	{
	public:
		~CGarhuishou() //类的析构函数中
		{
			if (MyCAS::m_instance)
			{
				delete MyCAS::m_instance;
				MyCAS::m_instance = NULL;
			}
		}
	};

	void func()
	{
		cout << "测试" << endl;
	}
};

//类静态变量初始化
MyCAS  *MyCAS::m_instance = NULL;

//线程入口函数
void mythread()
{
	cout <<"我的线程开始执行了" << endl;
	MyCAS *p_a = MyCAS::GetInstance(); //这里可能就有问题了
	cout << "我的线程执行完毕了" << endl;
}
int main()
{
	std::thread myobj1(mythread);
	std::thread myobj2(mythread);

	myobj1.join();
	myobj2.join();

	return 0;
}

4.std::call_once()

C++11引入的函数,该函数的第二个参数是一个函数名a();

std::call_once()功能是能够保证函数a()只被调用一次,具备互斥量这种能力,而且效率上比互斥量消耗的资源更小;

std::call_once()需要与一个标记结合使用,这个标记std::once_flag;其实once_flag是一个结构;

std::call_once()就是通过这个标记决定对应函数a()是否执行,调用call_once()成功后,std::call_once()就把这个标记设置为一种已调用状态,后续继续调用std::call_once(),只要once_flag被设置为了“已调用”状态,那么对应的函数a()就不会再被执行了;实例代码如下:

#include<iostream>
#include<thread>
#include<string>
#include<vector>
#include<list>
#include<mutex>

using namespace std;

std::mutex resource_mutex;
std::once_flag g_flag;//这是个系统定义的标记

class MyCAS
{
	static void CreateInstance()//只被调用一次
	{
		std::chrono::microseconds dura(20000);
		std::this_thread::sleep_for(dura);
		m_instance == new MyCAS();
		static CGarhuishou cl;
	}
private:
	MyCAS() {} //私有化了的构造函数

private:
	static MyCAS *m_instance; //静态成员变量

public:
	static MyCAS *GetInstance()
	{
		//两个线程同时执行到这里,其中一个线程要等另外一个线程执行完毕CreateInstance(),这里可以把g_flag看作一把锁
		std::call_once(g_flag, CreateInstance);
		cout << "call_once()执行完毕" << endl;
		return m_instance;
	}

	class CGarhuishou //类中套类,用来释放对象
	{
	public:
		~CGarhuishou() //类的析构函数中
		{
			if (MyCAS::m_instance)
			{
				delete MyCAS::m_instance;
				MyCAS::m_instance = NULL;
			}
		}
	};

	void func()
	{
		cout << "测试" << endl;
	}
};

//类静态变量初始化
MyCAS  *MyCAS::m_instance = NULL;

//线程入口函数
void mythread()
{
	cout << "我的线程开始执行了" << endl;
	MyCAS *p_a = MyCAS::GetInstance(); //这里可能就有问题了
	cout << "我的线程执行完毕了" << endl;
}
int main()
{
	std::thread myobj1(mythread);
	std::thread myobj2(mythread);

	myobj1.join();
	myobj2.join();

	return 0;
}

注:该文是C++11并发多线程视频教程笔记,详情学习:https://study.163.com/course/courseMain.htm?courseId=1006067356

相关文章