C++单例模式的懒汉模式和饿汉模式详解

 更新时间:2022年03月13日 14:29:52   作者:TABE_  
这篇文章主要为大家详细介绍了C++懒汉模式和饿汉模式,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

懒汉模式

懒汉模式在第一次用到类实例的时候才会去实例化,就是不到调用getInstance函数时,这个类的对象是一直不存在的。懒汉本身是线程不安全的

#include <iostream>
using namespace std;
class Singelton{
private:
    Singelton(){
        m_count ++;
        printf("Singelton begin\n");
        Sleep(1000);// 加sleep为了放大效果
        printf("Singelton end\n");
    }
    static Singelton *single;//定义一个唯一指向实例的指针,并且是私有的
public:
    static Singelton *GetSingelton();//定义一个公有函数,可以获取这个唯一实例
    static void print();
    static int m_count;
};
 //将唯一指向实例的指针初始化为nullptr
Singelton *Singelton::single = nullptr;
int Singelton::m_count = 0;
Singelton *Singelton::GetSingelton(){
    if(single == nullptr){//判断是不是第一次使用
        single = new Singelton;
    }
    return single;
}
void Singelton::print(){
    cout<<m_count<<endl;
}
int main()
{
	singleton* a1 = singleton::GetInstance();
	cout << a1 << endl;
	a1->print();
	singleton* a2 = singleton::GetInstance();
	cout << a2 << endl;
	a2->print();
	system("pause");
	return 0;
}

懒汉模式的singleton类有以下特点:

1.他有一个指向唯一实例的静态指针,并且是私有的。

2.它有一个公有的函数,可以获取这个唯一的实例,并且在需要的时候创建该实例。

3.它的构造函数是私有的,这样就不能从别处创建该类的实例。

饿汉模式

饿汉模式在单例类定义的时候(即在main函数之前)就进行实例化。因为main函数执行之前,全局作用域的类成员静态变量m_Instance已经初始化,故没有多线程的问题。

#include <iostream>
#include <process.h>
#include <windows.h>
using namespace std;
class Singelton{
private:
    Singelton(){
        m_count ++;
        printf("Singelton begin\n");
        Sleep(1000);                            // 加sleep为了放大效果
        printf("Singelton end\n");
    }
    static Singelton *single;//定义一个唯一指向实例的指针,并且是私有的
public:
    static Singelton *GetSingelton();//定义一个公有函数,可以获取这个唯一实例
    static void print();
    static int m_count;
};
// 饿汉模式的关键:定义即实例化
Singelton *Singelton::single = new Singelton;
int Singelton::m_count = 0;
Singelton *Singelton::GetSingelton(){
    // 不再需要进行实例化
    //if(single == nullptr){
    //    single = new Singelton;
    //}
    return single;
}
void Singelton::print(){
    cout<<m_count<<endl;
}
int main()
{
	cout << "we get the instance" << endl;
	singleton* a1 = singleton::getinstance();
	singleton* a2 = singleton::getinstance();
	singleton* a3 = singleton::getinstance();
	cout << "we destroy the instance" << endl;
	system("pause");
	return 0;
}

线程安全的懒汉模式

在多线程环境下,懒汉模式的上述实现方式是不安全的,原因在于在判断instance是否为空时,可能存在多个线程同时进入if中,此时可能会实例化多个对象。于是出现了二重锁的懒汉模式,实现代码如下:

#include<iostream>
#include<mutex>
using namespace std;
/*单例模式:构造函数私有化,对外提供一个接口*/
//线程安全的单例模式
class lhsingleClass {
public:
	static lhsingleClass* getinstance()
	{//双重锁模式
		if (instance == nullptr)
		{//先判断是否为空,如果为空则进入,不为空说明已经存在实例,直接返回
            //进入后加锁
			i_mutex.lock();
			if (instance == nullptr)
			{//再判断一次,确保不会因为加锁期间多个线程同时进入
				instance = new lhsingleClass();
			}
			i_mutex.unlock();//解锁
		}
		return instance;
	}
private:
    static lhsingleClass* instance;
	static mutex i_mutex;//锁
	lhsingleClass(){}
};
lhsingleClass* lhsingleClass::instance=nullptr;
mutex lhsingleClass::i_mutex;//类外初始化
 
int main()
{
	lhsingleClass* lhsinglep5 = lhsingleClass::getinstance();
	lhsingleClass* lhsinglep6 = lhsingleClass::getinstance();
	cout << lhsinglep5 << endl;
	cout << lhsinglep6 << endl;
	system("pause");
	return 0;
}

此代码共进行了两次判断:

  • 先判断是否为空,如果为空则进入,不为空说明已经存在实例,直接返回。
  • 再判断一次,确保不会因为加锁期间多个线程同时进入。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容! 

 

相关文章

  • C++实现教职工信息管理系统课程设计

    C++实现教职工信息管理系统课程设计

    这篇文章主要为大家详细介绍了C++实现教职工信息管理系统课程设计,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • 基于C语言实现钻石棋游戏的示例代码

    基于C语言实现钻石棋游戏的示例代码

    独立钻石是源于18世纪法国的宫廷贵族的自我挑战类单人棋游戏,可以锻炼逻辑思维能力。本文将用C语言实现这一简单的游戏,感兴趣的小伙伴可以了解一下
    2023-02-02
  • c语言合并两个已排序数组的示例(c语言数组排序)

    c语言合并两个已排序数组的示例(c语言数组排序)

    如何将两个已排序数组合并成一个排序数组,下面我们给出使用c语言合并两个已排序数组的示例,需要的朋友可以参考下
    2014-03-03
  • C++浮点数在内存中的存储详解

    C++浮点数在内存中的存储详解

    大家好,本篇文章主要讲的是C++浮点数在内存中的存储详解,感兴趣的同学赶快来看一看吧,对你有帮助的话记得收藏一下
    2022-01-01
  • C语言详细讲解指针数组的用法

    C语言详细讲解指针数组的用法

    在C语言和C++等语言中,数组元素全为指针变量的数组称为指针数组,指针数组中的元素都必须具有相同的存储类型、指向相同数据类型的指针变量。指针数组比较适合用来指向若干个字符串,使字符串处理更加方便、灵活
    2022-05-05
  • C语言树状数组的实例详解

    C语言树状数组的实例详解

    这篇文章主要介绍了C语言树状数组的实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下
    2017-10-10
  • C/C++实现对STORM运行信息查看及控制的方法

    C/C++实现对STORM运行信息查看及控制的方法

    这篇文章主要介绍了C/C++实现对STORM运行信息查看及控制的方法,需要的朋友可以参考下
    2014-07-07
  • C++求解二叉树的下一个结点问题

    C++求解二叉树的下一个结点问题

    本文将通过C++求解以下问题:给定一个二叉树其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。文中示例代码讲解详细,感兴趣的可以了解一下
    2022-04-04
  • C语言之单向链表详解及实例代码

    C语言之单向链表详解及实例代码

    这篇文章主要介绍了C语言之单向链表的相关资料,及实例代码,帮助大家学习参考,,需要的朋友可以参考下
    2016-09-09
  • C语言实现简单职工信息管理系统

    C语言实现简单职工信息管理系统

    这篇文章主要为大家详细介绍了C语言实现简单职工信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-07-07

最新评论