6.单例设计模式共享数据分析,call_once

单例设计模式

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

using namespace std;

class MyCAS {//单例类
private:
	MyCAS() {}//私有化构造函数
	static MyCAS * m_instance;//静态成员变量
public:
	static MyCAS* GetInstance() {
		if (!m_instance) {
			m_instance = new MyCAS();
			static Release cl;
		}
		return m_instance;
	}
	class Release {//类中套类,用来释放对象
	public:
		~Release() {
			if (MyCAS::m_instance) {
				delete MyCAS::m_instance;
				MyCAS::m_instance = nullptr;
			}
		}
	};
};
//类静态变量初始化
MyCAS* MyCAS:: m_instance = nullptr;
int main() {
	MyCAS * p_a = MyCAS::GetInstance();
	//MyCAS * p_b = MyCAS::GetInstance();//只会创建一个对象
}

单例模式共享数据问题

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

using namespace std;

std::mutex resource_mutex;
class MyCAS {//单例类
private:
	MyCAS() {}//私有化构造函数
	static MyCAS * m_instance;//静态成员变量
public:
	static MyCAS* GetInstance() {
		//双重锁定(双重检查)提高效率
		//多加一个判断,以免一进来就要等锁加锁。。。
		if (!m_instance) {
			std::unique_lock<std::mutex>mymutex(resource_mutex);//自动加锁
			if (!m_instance) {
				m_instance = new MyCAS();//这句话不加锁可能会被多个线程执行,导致错误(指向不同区域)
				static Release cl;
			}
		}
		
		return m_instance;
	}
	class Release {//类中套类,用来释放对象
	public:
		~Release() {
			if (MyCAS::m_instance) {
				delete MyCAS::m_instance;
				MyCAS::m_instance = nullptr;
			}
		}
	};
};
//类静态变量初始化
MyCAS* MyCAS:: m_instance = nullptr;
//线程入口函数
void mythread() {
	cout << "我的线程开始执行了" << endl;
	MyCAS *p_a = MyCAS::GetInstance();
	cout << "我的线程执行完毕了" << endl;
}

int main() {

	//单例设计模式共享数据问题分析,解决
	//面临的问题:需要我们自己创建的线程(不是主线程)中来创建MyCAS这个单例对象,这种线程可能最少2个
	//虽然这两个线程是同一个入口函数,但会同时执行mythread
	std::thread myobj1(mythread);
	std::thread myobj2(mythread);
	myobj1.join();
	myobj2.join();
}

call_once解决数据共享问题

std::call_once();c++11引入的函数,该函数的第二个参数是一个函数名a()
call_once功能是能够保证函数a()只被调用一次
call_once具备互斥量这种能力,而且效率上比互斥量消耗的资源更少
call_once()需要与一个标记结合使用,这个标记std::once_flag,其实once_flag是一个结构;
call_once就是通过这个标记来决定对应的函数a()是否执行,调用call_once()成功后,call_once就把这个标记设置为已调用
后续再次调用call_once(),只要once_flag被设置为“已调用”,那么函数a()就不会再被执行了

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

using namespace std;

std::mutex resource_mutex;
std::once_flag g_flag;//系统定义的标记
class MyCAS {//单例类
private:
	static void CreateInstance() {
		//sleep 2s
		std::chrono::milliseconds dura(2000);
		std::this_thread::sleep_for(dura);
		cout << "CreateInstance()仅被执行1次" << endl;
		m_instance = new MyCAS();
		static Release cl;
	}
	MyCAS() {}//私有化构造函数
	static MyCAS * m_instance;//静态成员变量
public:
	static MyCAS* GetInstance() {
		//两个线程同时执行到这里,其中一个线程要等另外一个线程执行完毕CreateInstance
		std::call_once(g_flag, CreateInstance);
		cout << "call_once()执行完毕" << endl;
		return m_instance;
	}
	class Release {//类中套类,用来释放对象
	public:
		~Release() {
			if (MyCAS::m_instance) {
				delete MyCAS::m_instance;
				MyCAS::m_instance = nullptr;
			}
		}
	};
};
//类静态变量初始化
MyCAS* MyCAS:: m_instance = nullptr;
//线程入口函数
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();

	/*
			我的线程开始执行了
			我的线程开始执行了
			CreateInstance()仅被执行1次
			call_once()执行完毕
			我的线程执行完毕了
			call_once()执行完毕
			我的线程执行完毕了
	
	*/

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值