您现在的位置是:主页 > news > 做网站尽在美橙互联/成都seo推广
做网站尽在美橙互联/成都seo推广
admin2025/5/17 9:30:49【news】
简介做网站尽在美橙互联,成都seo推广,中信建设有限责任公司西安分公司,手机如何制作ppt文章目录单例模式两种单例模式饿汉式懒汉式单例模式 一个类不管创建多少次对象,永远只能得到该类型一个对象的实例。 很多时候,我们在程序设计的时候,对于某一类只需要生成其中一个对象。比如说对于MySQL数据库类来说,如果频繁的…
文章目录
- 单例模式
- 两种单例模式
- 饿汉式
- 懒汉式
单例模式
一个类不管创建多少次对象,永远只能得到该类型一个对象的实例。
很多时候,我们在程序设计的时候,对于某一类只需要生成其中一个对象。比如说对于MySQL数据库类来说,如果频繁的创建MySQL对象,那么会有海量的链接连接到MySQL数据库,对数据库来说是一个不小的负担。
但其实对于开发者来说,一个连接其实就能胜任与数据库的交互工作,这就是单例模式。
两种单例模式
而对于单例模式来说,又分为两种:懒汉式、饿汉式
两种单例模式:
懒汉式: 当获取实例对象时,对象才产生
饿汉式: 还没有获取实例对象时,对象已经产生了
饿汉式
可能大家已经想到了,利用static修饰的变量属于类这一特性来实现。确实也是这么做的:
1.构造函数私有化
2.定义static修饰的唯一实例对象
3.类外初始化
4.类中提供一个供外界获取的static接口
5.删除拷贝构造与赋值函数
class Singleton
{
public:static Singleton* get_instance(){//函数静态局部变量的初始化,在汇编指令上已经自动添加线程互斥指令了static Singleton instance;return &instance;}
private:static Singleton instance; //唯一的类的实例对象Singleton() //构造函数私有化{}Singleton(const Singleton&) = delete;Singleton operator=(const Singleton&) = delete;
};Singleton Singleton::instance;
这里我们可以看到,无论是多线程还是单线程,对于饿汉式来说,都是线程安全的。
懒汉式
既然有了饿汉式,而且饿汉式在多线程方面还是近乎完美的,那么又要懒汉式单例模式干什么呢?
设想一种情况:一个项目中有很多需要单例设计的类,如果其中大部分类呢又用不到,但是饿汉式会让他们都生成实例对象,这样就造成了内存资源一种浪费。
所以就需要懒汉式设计模式:
1.构造函数私有化
2.类中设计一个static修饰的指针并在类外初始化
3.提供一个供外部访问的static修饰的函数接口
4.函数接口中实现new一个实例对象
5.删除拷贝构造与赋值函数
mutex g_mutex;
class Singleton
{
public:static Singleton* get_instance(){if (instance == nullptr){lock_guard<mutex> lock(mutex);if (instance == nullptr){instance = new Singleton();}}return instance;}
private:static Singleton *volatile instance; //唯一对象指针//volatile 编译器在用到这个变量时必须每次//都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份Singleton() //构造函数私有化{}Singleton(const Singleton&) = delete;Singleton operator=(const Singleton&) = delete;
};
static Singleton* volatile instance = nullptr; //唯一对象
可以看到,我这里是加了一把锁g_mutex的,而且在对外提供的static函数接口内实现了双重 if 判断,这是因为,如果不加锁的话:
static Singleton* get_instance()
{if (instance == nullptr){instance = new Singleton();}return instance;
}
试想一种情况:如果两个线程同时进入get_instance函数,并且此时他们进入时的instance都是nullptr,那么这两个线程都会new一个Singleton对象,但是instance只能去指向其中的一个,这样就会造成有一个Singleton的内存泄漏。
而在锁后又加一层 if 判断的原因是:
if (instance == nullptr)
{lock_guard<mutex> lock(mutex);if (instance == nullptr){instance = new Singleton();}
}
还是两个线程,进入都判断instance为nullptr,都通过了第一个if,其中线程A获得锁,创造了一个Singleton对象,然后释放锁;线程B 获得锁,如果不加第二个 if 的话无疑会再次创造一个实例对象,这是我们不希望看见的。