1. 单例模式
1.1 概念
只能创建一个对象
如何保证只能创建一个对象?
1.2 示例
class Object//正确,静态成员不属于对象,构建obj对象只有value,没有内部对象
{
public:
int value;
static Object obj;
};
1.3 单例模式与静态成员
class Object
{
private:
int value;
static Object instance;
static int num;
private:
Object(int x=0) :value(x) {}
Object(const Object& obj) = delete;
Object& operator=(const Object& ob) = delete;
public:
static Object& GetInstance()//取地址只能用指针或者引用方式返回,不能以值直接返回
{
return instance;
}
};
Object Object::instance(10);//静态成员类型 代表静态成员类里面的静态成员
int main()
{
Object& obja = Object::GetInstance();//静态函数可以通过类名直接访问
Object& objb = obja.GetInstance();
cout << &obja << endl;
cout << &objb << endl;
return 0;
}
运行结果:打印地址相同,因为引用的是同一个对象
线程安全
#define _CRT_SECURE_NO_WARNINGS
#include"stdio.h"
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<vector>
#include<map>
#include<list>
#include<thread>
using namespace std;
class Object
{
private:
int value;
static Object instance;
static int num;
private:
Object(int x=0) :value(x) {}
Object(const Object& obj) = delete;
Object& operator=(const Object& ob) = delete;
public:
static Object& GetInstance()//取地址只能用指针或者引用方式返回,不能以值直接返回
{
return instance;
}
};
Object Object::instance(10);//静态成员类型 代表静态成员类里面的静态成员 线程安全
//线程化
void funa()
{
Object& obja = Object::GetInstance();
cout << &obja << endl;
}
void funb()
{
Object& objb = Object::GetInstance();
cout << &objb << endl;
}
int main()
{
thread thra(funa);
thread thrb(funb);
//等待线程结束函数
thra.join();
thrb.join();
return 0;
}
单例模式-饿汉模式
class Object
{
private:
int value;
private:
Object(int x=0) :value(x) {}
Object(const Object& obj) = delete;
Object& operator=(const Object& ob) = delete;
public:
static Object& GetInstance()//取地址只能用指针或者引用方式返回,不能以值直接返回
{
static Object instance(10);//饿汉模式:在使用之前创建好实例,线程安全
return instance;
}
};
void funb()
{
//在底层初始化实现
//有标记位,线程不安全,会产生竞争资源状况
int x = 10;
static int b = x;
//直接初始化
static int a = 10;
单例模式-懒汉模式
单例模式产生多个对象,在需要的时候在构建对象
#define _CRT_SECURE_NO_WARNINGS
#include"stdio.h"
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<vector>
#include<map>
#include<list>
#include<thread>
using namespace std;
class Object
{
private:
int value;
static Object* pobj;
private:
Object(int x=0) :value(x) {}
Object(const Object& obj) = delete;
Object& operator=(const Object& ob) = delete;
public:
//懒汉模式不安全
static Object* GetInstance()
{
if (pobj == NULL)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));//睡眠10毫秒
pobj = new Object(10);
}
return pobj;
}
};
Object* Object::pobj = NULL;
void funa()
{
Object* pa = Object::GetInstance();
cout << pa << endl;
}
void funb()
{
Object* pb = Object::GetInstance();
cout << pb << endl;
}
int main()
{
thread tha(funa);
thread thb(funb);
tha.join();
thb.join();
return 0;
}
1.4 如何解决多线程安全问题?
加锁
#define _CRT_SECURE_NO_WARNINGS
#include"stdio.h"
#include<iostream>
#include<stdlib.h>
#include<assert.h>
#include<string.h>
#include<vector>
#include<map>
#include<list>
#include<thread>
#include<mutex>
using namespace std;
std::mutex mtx;//锁
class Object
{
private:
int value;
static Object* pobj;
private:
Object(int x=0) :value(x) {}
Object(const Object& obj) = delete;
Object& operator=(const Object& ob) = delete;
public:
//懒汉模式不安全
static Object* GetInstance()
{
std::lock_guard<std::mutex> lock(mtx);//加锁可以让线程安全
if (pobj == NULL)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));//睡眠10毫秒
pobj = new Object(10);
}
return pobj;
}
};
Object* Object::pobj = NULL;
void funa()
{
Object* pa = Object::GetInstance();
cout << pa << endl;
}
void funb()
{
Object* pb = Object::GetInstance();
cout << pb << endl;
}
int main()
{
thread tha(funa);
thread thb(funb);
tha.join();
thb.join();
return 0;
}
加锁之后在同一地址,说明构建对象相同,线程安全
次序问题导致线程不安全