Singleton mode and call_once

//Design Pattern
/*1.程序灵活,维护方便,但是接管难
2.适用于大项目,不要生搬硬套
*/
//单例设计模式:
/*
整个程序中某个或者某些特殊的类,他们只能创建一个对象(一般为数据共享)。
单例类,只能生成一个对向。
设计模式共享数据问题分析,解决
如果数据是只读的,多个线程同时调用没有问题,所以单例一般适合在只读数据上使用。
一般单例用来储存全局唯一变量。例如银行的货币的汇率。
建议:在创建其他线程之前,在主线程中就把单例的成员初始化和数据装载。
*/
//在子线程中创建单例
/*
面临问题:需要在我们自己创建的线程中创建MYCAS这个单例类对象,这样的线程最少两个、
所以GetInstance()这种成员函数需要互斥。
*/
//std::call_once()
/*
c++11,该函数的第二个参数是一个函数名,eg:a()
call_once功能时能够保证a()只被调用一次,具备互斥量这样的能力,而且效率比互斥量更高
但是需要和std::onec_flag这个标记结合使用。onec_flag是一个结构。
call_onec()就是通过这个标记来决定对应的函数a()是否执行,调用call_once()成功后,call_once
就把这个标记设置为一种一调用状态
once_flag设置为一调用状态,那么对应的函数a()就不会再被执行了。
*/
#include<iostream>
#include<thread>
#include<mutex>
using namespace std;

mutex resource_mutex;//因为是静态函数引用,所以不能添加在类的private里。
std::once_flag g_flag;

class MyCAS {
    
    //单例类
private:
	MyCAS() {
    
    }//私有化了一个构造函数
	static MyCAS* m_instance;//静态成员变量m_instance 指向MyCAS可全局使用
	
	//once_flag
	static void CreateInstance()//只被调用一次
	{
    
    
		std::chrono::milliseconds dura(2000);
		std::this_thread::sleep_for(dura);
		m_instance = new MyCAS();
		cout << "Creat is runing" << endl;
		static CGarhuishou c1;
	}

public:
	

	static MyCAS* GetInstance()//创建对象接口
	{
    
    
		/*if (m_instance == NULL) {//双重检查增加效率
			//低效率原因
			/*
			只要线程想使用单例类的数据,都需要调用getInstance来获取单例对象的指针。
			多个线程中调用,那么就会造成多个线程因为互斥锁而产生排队现象,
			所以我们需要提前判断是否对象已经被创建而增加效率。
			*/

			/*unique_lock<mutex>CasLock(resource_mutex);//自动加锁,单独使用的话效率低
			if (m_instance == NULL) {//第二次创建的时候m_instance不为空,直接返回全局的静态m_instance
				m_instance = new MyCAS;
				static CGarhuishou c1;
			}
		}*/ 

		//once_flag
		std::call_once(g_flag,CreateInstance);
		cout << _threadid<<"CallOnce is done." << endl;
		//两个线程执行到这里,有一个就需要等待,一旦一个函数执行,flag就由0变1;

		return m_instance;
	}

	class CGarhuishou//类中套类,用来释放对象
	{
    
    
	public:
		~CGarhuishou()
		{
    
    
			if (MyCAS::m_instance !=NULL)
			{
    
    
				delete MyCAS::m_instance;
				MyCAS::m_instance = NULL;
			}
		}
	};
	
	void func()
	{
    
    
		cout << "test" << endl;
	}


};


void mythread()
{
    
    
	cout << "Thread " << _threadid << " is runing" << endl;
	MyCAS* p_a = MyCAS::GetInstance();//
	cout << _threadid << "finish work." << endl;

}

//类的静态变量初始化
MyCAS* MyCAS::m_instance = NULL;
int main()
{
    
    
	/*MyCAS* p_test = MyCAS::GetInstance();//创建一个对象,返回该类(MyCAS)对象的指针。
	p_test->func();//装载数据
	MyCAS::GetInstance()->func();*/

	//两个线程同时执行mythread的问题
	/*
	线程一执行到if(m_instance==NULL)后,时间片切换到线程二,
	线程二执行完整跳出if循环后创建了m_instance,这时时间片切换到线程一,
	线程一继续执行if后的语句也创建了也一个m_instance,这就破坏了单例的单一性。
	所以我们需要添加互斥锁。
	*/
	thread myobj1(mythread);
	thread myobj2(mythread);

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

	return 0;


}

Guess you like

Origin blog.csdn.net/guanxunmeng8928/article/details/108073874