c++单例模式的介绍与实现

1.单例模式

  单例模式是基本的设计模式之一,它属于创建型模式,提供一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。

  在程序设计上须保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

  在进行单例类封装的时候,避免被调用方构造,构造函数需私有化。

2. 饿汉单例模式

  程序启动时就实例化了该对象,并没有推迟到第一次使用该对象时再进行实例化。

  在这样的情况下,多线程调用单例和它的方法,只会进行实例的使用而不会进行实例的创建。

  为什么说它是线程安全的呢?

  因为C++11保证静态局部变量的初始化过程是线程安全的,一个线程在初始化 m 的时候,其他线程执行到 m 的初始化这一行的时候,就会挂起。

  代码实现如下:

class Singleton{
public:
    static Singleton* m_instance_ptr;
    static Singleton* get_instance() {
        return m_instance_ptr;
    }
private:
    Singleton() { }
};

Singleton* Singleton::m_instance_ptr = new Singleton();

int main(){
    Singleton* instance1 = Singleton::get_instance();
    Singleton* instance2 = Singleton::get_instance();
    return 0;
}

  一句话总结:因为类实例化就会占用内存,所以浪费资源,但由于提前初始化了实例,所以效率较高,且不存在线程安全问题。

  由于程序流程是程序员控制的,所以在饿汉模式下,只要能保证前期能创建实例,就不存在那些抢占多实例的问题。

  如果在程序运行过程中没有使用到实例对象,那么在饿汉模式下该实例对象就被浪费掉了,这个场景可能需要使用懒汉单例模式。

3. 懒汉单例模式

  懒汉单例模式会在第一次使用它的时候才进行对象的实例化。

  代码实现如下:

class Singleton {
public:
    static Singleton* m_instance_ptr;
    static Singleton* get_instance() {
        if(m_instance_ptr == NULL)
            m_instance_ptr = new Singleton();
        return m_instance_ptr;
    }
private:
    Singleton() { }
};

Singleton* Singleton::m_instance_ptr = NULL;

int main(){
    Singleton* instance1 = Singleton::get_instance();
    Singleton* instance2 = Singleton::get_instance();
    return 0;
}

  如果多线程竞争创建实例时,需要考虑加锁。

  代码实现如下:

class Singleton {
public:
    static Singleton* m_instance_ptr;
    static std::mutex m_mutex;
    static Singleton* get_instance() {
        // double-check来保证不会每次进来都去获取锁,来提高性能,先判断不为空的话,直接返回了数据
        if(m_instance_ptr == NULL) {
            m_mutex.lock();
            if(m_instance_ptr == NULL)
                m_instance_ptr = new Singleton();
            m_mutex.unlock();
        }
        return m_instance_ptr;
    }
private:
    Singleton() { }
};

Singleton* Singleton::m_instance_ptr = NULL;
std::mutex Singleton::m_mutex;

void thread_instance_do() {
    Singleton* instance = Singleton::get_instance();
    while(1) {
        // do something
    }
}

int main(){
    std::thread thread1(thread_instance_do);
    std::thread thread2(thread_instance_do);
    thread1.join();
    thread2.join();
    return 0;
}

  一句话总结:由于延迟加载,所以节省资源,导致效率低,且存在线程安全问题。


  参考文章

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小爱玄策

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值