单例模式

    首先,面向对象很好地解决了“抽象”的问题,但是必不可免地要付出一定的代价。对于通常情况讲,面向对象的成本大多可以忽略不计。但是某些情况,面向对象所带来的成本必须谨慎处理。单例模式就可以控制这种成本。

  • 为什么要使用单例模式

     在软件系统设计中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑性正确、以及良好的效率。如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?这应该是设计者的责任,而不是使用者的责任。

  • 主要解决的问题

     一个全局使用的类频繁地创建与销毁。

  • 怎么实现

     构造函数是私有的。

  • 单例模式的优点

      在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存);

      避免对资源的多重占用(比如写文件操作,Windows 是多进程多线程的,在操作一个文件的时候,就不可避免地出现多个进程或线程同时操作一个文件的现象,所以所有文件的处理必须通过唯一的实例来进行。);

  • 单例模式的缺点

      没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例化。

需要注意:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。

  • 懒汉式实现单例模式,最后一个函数是双检查锁的方法   
class Singleton{
private:
    Singleton();
    Singleton(const Singleton& other);
public:
    static Singleton* getInstance();
    static Singleton* m_instance;
};

Singleton* Singleton::m_instance = nullptr;

//线程非安全版本
Singleton* Singleton::getInstance(){
    if(m_instance == nullptr){
        m_instance = new Singleton();
    }
    return m_instance;
}

//线程安全版本,但是代价高,降低了多线程的并发性,互斥锁
Singleton* Singleton::getInstance(){
    Lock lock;//对这个函数加锁
    if(m_instance == nullptr){
        m_instance = new Singleton();
    }
    return m_instance;
}

//线程安全版本,解决了互斥锁的问题,这种方法是双检查锁。但是会存在reorder不安全的问题,不能使用
Singleton* Singleton::getInstance(){
    if(m_instance == nullptr){
        Lock lock;
        if(m_instance == nullptr) //注意这里为什么要加这条if,如果你加的话,多线程情况有可能创建多个实例,考虑原因
            m_instance = new Singleton();
    }
    return m_instance;
}
//经过研究者大量的额实验发现,这种情况很有肯能发生,因此不能使用
//我们认为m_instance = new Singleton();底层的执行顺序是分三步的
//第一步:分配内存 第二步:调用构造器 第三步:把指针赋给m_instance 
//但是CPU在进行指令优化的后,可能把第二步和第三步的执行顺序调换,如果这个时候另一个线程进来在第一个
//判断处就不会是nullptr,但是实际上还没有执行构造函数,因此,这个时候执行return会出错


  • 恶汉式实现单例模式
//这种方式比较常用,但容易产生垃圾对象。
//优点:没有加锁,执行效率会提高。缺点:类加载时就初始化,浪费内存。
class Singleton{
private:
    Singleton();
    Singleton(const Singleton& other);
public:
    static Singleton* getInstance(){return m_instance;};
    static Singleton* m_instance; 
};

Singleton* m_instance = new Singleton();

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值