ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

c++设计模式①单例模式 1.懒汉式

2021-09-05 15:06:37  阅读:153  来源: 互联网

标签:Singleton 访问 c++ instance mutex 单例 设计模式 指针


1.定义

单例模式(Singleton),保证一个类仅有一个实例,并提供一个访问它的全局访问点。[DP]

2.理解

因为需要只有一个实例对象,最好的控制方式就是类自身来控制,而不是在其他类或者全局变量来控制实例对象的创建。

我对于定义的理解是,为了保证一个类仅有一个实例,所以必须一个访问它的全局访问点。保证一个类仅有一个实例,换言之就是类的构造不对外开放,由其他方式来提供给外部使用,即提供一个访问的全局访问点或者接口。

3.懒汉式(使用时再创建)

这样我们就可以大概获得Singleton类的大概结构:

#pragma once

class Singleton
{
private:  //①构造函数私有化
	Singleton(){};

public:  
	//②提供一个全局访问点,由它来提供给外部Singleton的指针
	//因为要实现在没有Singleton对象的情况下获取到Singleton的指针,所以使用static
	//这样就可以通过类名来获取到对象指针了
	static Singleton* GetInstance();

private: //③ 用来返回的唯一的实例指针
	static Singleton* m_instance;

};
#include "Singleton.h"


//类内的全局变量需要独立初始化
Singleton* Singleton::m_instance = nullptr;

//懒汉式 即 使用再加载
Singleton* Singleton::GetInstance()
{
    if (!m_instance)  //如果m_instance等于nullptr,进入
    {
        m_instance = new Singleton();  //构造函数私有的目的就在于此
    }
    return m_instance;
}

以上的单例模式在单线程是安全的,但是在多线程的时候会出现问题。假设有两个线程同时访问GetInstance函数,且同时走到if (!m_instance) 的时候,会都得到m_instance为nullptr的信息,这样就会各自都会创建对象,这样对象就不在唯一了,与单例模式的定义不符合。主要原因是在创建完成前,大家都可以去创建。

既然会同时访问,那就加锁,

#pragma once
#include <mutex>

class Singleton
{
private:  //①构造函数私有化
	Singleton() {};

public:  
	//②提供一个全局访问点,由它来提供给外部Singleton的指针
	//因为要实现在没有Singleton对象的情况下获取到Singleton的指针,所以使用static
	//这样就可以通过类名来获取到对象指针了
	static Singleton* GetInstance();

private: //③ 用来返回的唯一的实例指针
	static Singleton* m_instance;

	static std::mutex m_mutex;
};

#include "Singleton.h"


//类内的全局变量需要独立初始化
Singleton* Singleton::m_instance = nullptr;
std::mutex Singleton::m_mutex;

//懒汉式 即 使用再加载
Singleton* Singleton::GetInstance()
{
    m_mutex.lock();
    if (!m_instance)  //如果m_instance等于nullptr,进入
    {
        m_instance = new Singleton();  //构造函数私有的目的就在于此
    }
    m_mutex.unlock();
    return m_instance;
}

这样就保证了单例模式的安全,但是现在的代码,每次GetInstance都需要加锁,这样带来的开销很大,会降低效率。所以就有了deouble-check机制的产生。再回顾我们刚刚说的,主要原因是在创建完成前,大家都可以去创建。但如果已经创建好,再有多线程访问,那就不会有这些问题。

所以我们要对后续访问去锁,对创建加锁:

#include "Singleton.h"


//类内的全局变量需要独立初始化
Singleton* Singleton::m_instance = nullptr;
std::mutex Singleton::m_mutex;

//懒汉式 即 使用再加载
Singleton* Singleton::GetInstance()
{
    if (!m_instance)
    {
        m_mutex.lock();
        if (!m_instance)  //如果m_instance等于nullptr,进入
        {
            m_instance = new Singleton();  //构造函数私有的目的就在于此
        }
        m_mutex.unlock();
    }
    return m_instance;
}

这就是double-check模式,这样创建完成后的后续只要走第一个if判断,而且不会进if内加锁灯操作,这样就维护了后续的效率。

如果想要主动销毁到Singleton对象,可以给类添加一个Release函数,来完成对单例对象的主动释放。谨慎,可能会带来野指针的问题,因为可能其他地方还持有着指针,你这时候释放了指针的空间,那么持有者后续进行访问的时候会出现问题。

至此,懒汉式单例就结束了。

标签:Singleton,访问,c++,instance,mutex,单例,设计模式,指针
来源: https://blog.csdn.net/ListenAlone/article/details/120114330

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有