#include <iostream>
#include <thread>
#include <mutex>
using namespace std;
mutex resource_mutex; //增加互斥量
once_flag g_flag; //系统定义的标记
//较实用的单例类
class MyCAS
{
private:
//将构造函数私有化
MyCAS()
{
}
private:
static MyCAS * m_instance; //静态成员变量
public:
/*
//与call_once配合使用
static void CreateInstance() //只被调用一次的函数
{
m_instance = new MyCAS();
static CGarhuishou c1;
}
*/
static MyCAS *GetInstance() //如果m_instance为空,则创建;否则返回已存在的对象指针
{
//如果m_instance != NULL,则表示m_instance肯定被new过了
//如果m_instance == NULL,不代表m_instance一定没被new过(可能在申请加锁互斥量(为了new)时,被别的线程new了)
if (m_instance == NULL) //双重锁定(双重检查),提高效率,避免每次调用GetInstance()都要申请加锁互斥量
{
unique_lock<mutex> my_mutex(resource_mutex); //自动加锁解锁
if (m_instance == NULL)
{
m_instance = new MyCAS(); //如果有多个线程,不加互斥量程序就会有问题
static CGarhuishou c1; //用来释放m_instance;
}
}
//call_once(g_flag, CreateInstance); //call_once,两个线程同时执行到这里,其中一个线程A等待另外一个线程B执行完毕,然后B执行完毕,g_flag被修改为已被执行的状态,A就不再执行。
return m_instance;
}
class CGarhuishou //类中套类 用来释放对象
{
public:
~CGarhuishou()
{
if (MyCAS::m_instance )
{
delete MyCAS::m_instance;
MyCAS::m_instance = NULL;
}
}
};
};
//类静态变量初始化
MyCAS *MyCAS::m_instance = NULL;
void mythread()
{
cout << "我的线程开始执行了" << endl;
MyCAS *p_a = MyCAS::GetInstance(); //如果不互斥,会出现的问题:
cout << "我的线程执行完毕了" << endl;
return;
}
int main()
{
//一:设计模式概谈
//设计模式:代码的一些写法(跟常规写法不太一样)。程序灵活,维护起来可能方便,但别人接管、阅读代码都会很痛苦
//应付特别大的项目的时候,把项目的开发经验、模块划分经验,总结整理成设计模式
//小项目强行用设计模式理念写出来的代码是很晦涩的,要活学活用,不要生搬硬套,深陷其中,本末倒置
//设计模式有独特的优点
//二:单例设计模式(使用的频率较高)
//整个项目中,有某个或某些特殊的类(单例类),属于该类的对象,只能创建1个,多了创建不了。
//MyCAS a1; //将构造函数私有化后,无法这样创建对象
//MyCAS a2;
//MyCAS *p_a = MyCAS::GetInstance(); //创建一个对象,返回该类对象的指针
//MyCAS *p_b = MyCAS::GetInstance(); //不会再创建新的,会返回已有的对象的指针
//三:单例设计模式共享数据问题分析、解决
//面临的问题:需要在我们自己创建的线程(而不是主线程)中来创建 MyCAS这个单例类的对象,这种线程可能不止一个
//此时GetInstance()这种成员函数需要互斥
thread mytobj1(mythread);
thread mytobj2(mythread); //线程入口函数均为mythread
mytobj1.join();
mytobj2.join();
//四:std::call_once(); C++11引入的函数,该函数的第二个参数是一个函数名
//功能是能够保障函数A()只被调用一次
//具备互斥量的能力,而且效率上比互斥量消耗的资源更少
//需要与一个标记结合使用。标记是 std::once_flag,是一种结构。就是通过这个标记来决定对应的函数是否执行,执行后会更改once_flag状态
return 0;
}