该类负责创建自己的对象,确保只有单个对象被创建,提供了一种唯一访问对象的方式。
注意
一个类只能有一个实例。
类必须自己创建自己的唯一实例
为所有对象提供这一实例
分类:
懒汉式
在使用时才进行创建。
饿汉式
不管是否会被使用都进行创建。
应用实例
一个班级只有一个班主任
一些设备管理器,输出时只能有一台打印机正在运行。
实现
#include<iostream>
using namespace std;
class single
{
public:
single()
{
cout << "构造函数" << endl;
}
static single *get();
private:
static single *ptr;
};
single *single::ptr = nullptr;//懒汉式 使用时进行创建
//single *single::ptr = new single; //饿汉式
single *single::get()
{
if (ptr == nullptr)
{
ptr = new single;
}
return ptr;
}
int main()
{
single *p1 = single::get();
single *p2 = single::get();
if (p1 != p2)
{
cout << "不是同一个对象" << endl;
} else
{
cout << "是同一个对象" << endl;
}
system("pause");
return 0;
}
多线程下饿汉式会出现问题
如果进入if判断,这个时候进行线程间切换,新的线程认为没有创建实例,会进行创建,再切换为之前的线程,两个同时创建,有几个线程就创建几个实例。
解决
第一种方法:
多线程安全版本 (加锁)
创建了一个临时变量lock 在函数执行完毕 rerurn释放锁。
禁止两个锁同时进入。可以保证对象全局唯一,但是代价太大,在高并发的情况下,我只需要读但是也不让我获取。
第二种方法:
如果已经存在,我直接返回就行了,不存在才需要创建进行加锁。
为什么需要两次判断
假如我把里面的都没有创建线程,进入了48行 ,即使加锁,两个线程还是都会创建 ,加锁没有意义。
锁在之前 代价过高,锁在之后,没有意义。 ------> 需要两次判断