单例模式中的懒汉模式和饿汉模式

在阅读《Effective C++》时,接触到了单例模式,而对于其所包含的懒汉模式和饿汉模式,现做如下笔记:

1 单例模式

首先要知道单例模式是什么。单例模式是一种设计模式,就是**保证一个类仅有一个实例,并提供一个访问它的全局访问点。**而懒汉模式和饿汉模式的区别则在于,该实例的创建时机不同,见如下。

2 懒汉模式

顾名思义,该模式很“懒”,所以实例要在迫不得已的情况下才被创建,即需要使用到该实例的时候才创建出来。如下有个懒汉的小demo:

class Singleton{
	static Singleton* ins;
    Singleton(){}
    Singleton* getInstance(){
        if (ins == nullptr){
            ins = new Singleton();
        }
        return ins;
    }
};
static Singleton* Singleton::ins = nullptr; // 静态成员变量需要在类外定义

3 饿汉模式

饿汉则是,在第一次定义这个单例类的时候就要进行实例化,这样之后就可以随取随用,看这个demo:

class Singleton{
	static Singleton* ins = new Singleton();
    Singleton(){}
    Singleton* getInstance(){
        return ins;
    }
};

4 懒汉模式和饿汉模式的安全性对比

首先,饿汉模式是具备线程安全性的。这是因为饿汉在线程还没有创建的时候,就已经实例化出来了,所以保证了线程安全性。

而对于懒汉模式,由于是在使用的时候,实例才会被创建出来,所以如果当前环境下有多个线程时,当这些线程需要用到该实例时,就会调用getInstance方法,而这个实例是静态变量,只会存在一个,那么那么多个线程都去创建这个实例的话,就会出现覆盖结果,导致最后return的这个实例不知道是哪个线程创建的。所以为了解决这个问题,就需要用到同步锁,用互斥锁即可解决。在多线程环境下,互斥锁以全局变量或者静态变量定义,这样每个线程都能使用到这个锁。那么懒汉模式的demo可改为如下:

class Singleton{
	static Singleton* ins;
	static pthread_mutex_t mutex;
    Singleton(){}
    Singleton* getInstance(){
        if (ins == nullptr){
            pthread_mutex_lock(&mutex);
            if (ins == nullptr){
                ins = new Singleton();
            }
            pthread_mutex_unlock(&mutex);
        }
        return ins;
    }
};
// 静态成员变量需要类外定义
static Singleton* Singleton::ins = nullptr;
static pthread_mutex_t Singleton::mutex = PTHREAD_MUTEX_INITIALIZER; // mutex可以这样初始化

这样,懒汉模式也能保证线程安全了。

5 懒汉模式与饿汉模式的效率对比

  • 从执行效率上来说,因为懒汉模式会有加锁、解锁等额外操作,所以效率会比饿汉模式低;
  • 从内存使用上来说,因为饿汉模式在定义类的时候,就会实例化,所以实例会一直占用着内存,而懒汉模式是在使用的时候才会实例化,因此懒汉模式的内存使用效率上会更高。

6 单例模式的应用场景

  • 当系统只需要一个实例对象时,或者考虑到资源消耗太大而只允许创建一个对象的时候,可以使用单例模式;
  • 当客户调用类的单个实例,而只允许使用一个公共访问点(除了该访问点之外不允许通过其他方式来访问该实例)时,可以使用单例模式。

参考文章:

(47条消息) 单例模式中的懒汉模式和饿汉模式是什么?区别又是什么?_因为我的心的博客-CSDN博客_懒汉模式和饿汉模式区别

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值