您现在的位置是:主页 > news > 做网站尽在美橙互联/成都seo推广

做网站尽在美橙互联/成都seo推广

admin2025/5/17 9:30:49news

简介做网站尽在美橙互联,成都seo推广,中信建设有限责任公司西安分公司,手机如何制作ppt文章目录单例模式两种单例模式饿汉式懒汉式单例模式 一个类不管创建多少次对象,永远只能得到该类型一个对象的实例。 很多时候,我们在程序设计的时候,对于某一类只需要生成其中一个对象。比如说对于MySQL数据库类来说,如果频繁的…

做网站尽在美橙互联,成都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 的话无疑会再次创造一个实例对象,这是我们不希望看见的。