1.设计模式概谈
设计模式:代码的一些写法;程序灵活,维护方便,但是代码可读性不高。
2.单例设计模式
整个项目中有某个或者特殊的类,该类只能创建一个对象。
单例类写法及创建对象方法如下:
#include <iostream>
using namespace std;
class Single_Class//单例类
{
private:
Single_Class() {};//私有化构造函数
static Single_Class *m_instance;//静态成员变量
public:
static Single_Class *GetInstance()
{
if (m_instance == NULL)
{
m_instance = new Single_Class;
static Deletex dl;
}
return m_instance;//0x00a0d098
}
void func()
{
cout << "测试" << endl;
}
class Deletex //用来释放对象
{
public:
~Deletex()
{
if (Single_Class::m_instance)
{
delete Single_Class::m_instance;
Single_Class::m_instance = NULL;
}
}
};
};
//类静态变量初始化
Single_Class *Single_Class::m_instance = NULL;
int main()
{
Single_Class *pa = Single_Class::GetInstance();//创建一个单例类对象,返回Single_Class类的指针
Single_Class *pb = Single_Class::GetInstance();//虽然看着好像创建了两个类指针,但是pa pb都是指向一个对象
pa->func();
Single_Class::GetInstance()->func();
return 0;
}
3.单例设计模式共享数据问题分析与解决
不止一个子线程创建单例类时,可能面临GetInstance()这种成员函数出现数据竞争,所以要考虑互斥问题。
以下是单例设计模式中双重锁定+互斥量的写法:
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include<mutex>
using namespace std;
std::mutex mylock;
class Single_Class//单例类
{
private:
Single_Class() {};//私有化构造函数
static Single_Class *m_instance;//静态成员变量
public:
static Single_Class *GetInstance()
{
if (m_instance == NULL) //双重检查,提高执行效率
{
std::unique_lock<mutex> ml(mylock);
if (m_instance == NULL)
{
m_instance = new Single_Class;
static Deletex dl;
}
}
return m_instance;
}
void func()
{
cout << "测试" << endl;
}
class Deletex //用来释放对象
{
public:
~Deletex()
{
if (Single_Class::m_instance)
{
delete Single_Class::m_instance;
Single_Class::m_instance = NULL;
}
}
};
};
//类静态变量初始化
Single_Class *Single_Class::m_instance = NULL;
void mythread()
{
cout << "\n我的线程开始执行了" << endl;
Single_Class *pa = Single_Class::GetInstance();
cout << "\n我的线程执行完毕了" << endl;
return;
}
int main()
{
//两个线程同时执行GetInstance()
std::thread myobj1(mythread);
std::thread myobj2(mythread);
myobj1.join();
myobj2.join();
return 0;
}
4.std::call_once()
call_once第一个参数是标记(std::once_flag),第二个参数是函数名a。call_ince的第一次执行完函数a后,标记会被更改状态。其他线程也调用call_once时,会通过标记的状态得知此函数已经被执行过,就不会再次执行函数a了。所以call_once的功能是能够保证函数a只被调用一次。
从意义上讲,call_once具备互斥量能力,效率上,比互斥量消耗的资源少。
#include <iostream>
#include <thread>
#include <vector>
#include <list>
#include<mutex>
using namespace std;
std::mutex mylock;
std::once_flag flag;//系统定义的标记
class Single_Class//单例类
{
private:
Single_Class() {};//私有化构造函数
static Single_Class *m_instance;//静态成员变量
public:
static void CreateInstance()//只被调用一次的函数
{
cout << "\nCreateInstance已经被线程" << std::this_thread::get_id() << "调用" << endl;
std::chrono::milliseconds dura(2000);
std::this_thread::sleep_for(dura);
m_instance = new Single_Class;
static Deletex dl;
}
static Single_Class *GetInstance()
{
std::call_once(flag, CreateInstance);//两个线程同时执行到这里,其中一个线程要等另外一个线程执行完毕CreateInstance,flag会被标记,另一个线程根据flag标记不会继续执行CreateInstance
cout <<"\n线程"<< std::this_thread::get_id() << "call_once执行完毕" << endl;
return m_instance;
}
class Deletex //用来释放对象
{
public:
~Deletex()
{
if (Single_Class::m_instance)
{
delete Single_Class::m_instance;
Single_Class::m_instance = NULL;
}
}
};
};
//类静态变量初始化
Single_Class *Single_Class::m_instance = NULL;
void mythread()
{
cout << "\n线程" << std::this_thread::get_id() << "开始执行" << endl;
Single_Class *pa = Single_Class::GetInstance();
cout << "\n线程" << std::this_thread::get_id() << "执行完毕" << endl;
return;
}
int main()
{
//两个线程同时执行GetInstance()
std::thread myobj1(mythread);
std::thread myobj2(mythread);
myobj1.join();
myobj2.join();
return 0;
}