单例模式详解

本文主要介绍各种单例模式的原理,及其不同的实现方法。实现语言为C++

定义:单例模式–保证一个类仅有一个实例,并提供一个访问它的全局访问点。
这篇文章介绍以下四种单例模式的类型,也是较为常用的。
在这里插入图片描述
1 饿汉式单例

class Singleton {
private:

    //    Singleton() = default;   // 自动生成默认构造函数
    Singleton() {
        cout << "Singleton construct\n";
    }
    Singleton(const Singleton& s) = delete;    // 禁用拷贝构造函数
    Singleton& operator=(const Singleton& s) = delete; // 禁用拷贝赋值操作符
    static Singleton m_singleton;
public:
    static Singleton* getInstance(){
        return &m_singleton;
    }
};
Singleton Singleton::m_singleton;

2 懒汉式单例

class Singleton {
private:
//    Singleton() = default;  // 自动生成默认构造函数
    Singleton() {                           // 构造函数 会影响局部静态变量, 不能用隐式的构造函数
        cout << "Singleton construct\n";
    }
    Singleton(const Singleton& s) = delete;    // 禁用拷贝构造函数
    Singleton& operator=(const Singleton& s) = delete; // 禁用拷贝赋值操作符
public:
    static Singleton* getInstance(){
        static Singleton s_singleton;  // C++11线程安全, C++11之前不是线程安全  __cxa_guard_acquire 和 __cxa_guard_release
        return &s_singleton;
    }
};

3 双锁型单例模式

/* 双检查锁,但由于内存读写reorder不安全 因为C++创建对象时,会执行1、分配内存,2 调用构造,3 赋值操作三步操作,
然而现代CPU和编译器高并发下可能会进行乱序重排操作,因而创建对象new CSingleton的第2步可能会晚于第3步进行指令调用,
因而导致出现未定义的的行为。*/
class Singleton {
private:
    static Singleton *m_singleton;
    static mutex m_mutex;
    Singleton() = default;
    Singleton(const Singleton& s) = default;
    Singleton& operator=(const Singleton& s) = default;
    class GarbageCollector {
    public:
        ~GarbageCollector() {
            cout << "~GarbageCollector\n";
            if (Singleton::m_singleton) {
                cout << "free m_singleton\n";
                delete Singleton::m_singleton;
                Singleton::m_singleton = nullptr;
            }
        }
    };
    static GarbageCollector m_gc;
public:
    void *getSingletonAddress() {
        return m_singleton;
    }
    static Singleton* getInstance() {
        if (Singleton::m_singleton == nullptr){
            m_mutex.lock();  // 加锁,保证只有一个线程在访问线程内的代码
            if (Singleton::m_singleton == nullptr) { //再次检查
                m_singleton = new Singleton();  // 对象的new不是原子操作 1、分配内存,2 调用构造,3 赋值操作,到第3步的时候才是m_singleton非空
                                                //  1、分配内存,2 赋值操作 3 调用构造,到第2步的时候才是m_singleton非空
            }
            m_mutex.unlock();//解锁
        }
        return m_singleton;
    }
};
Singleton* Singleton::m_singleton = nullptr;
mutex Singleton::m_mutex;
Singleton::GarbageCollector Singleton::m_gc;

4 线程安全型单例

//线程安全的懒汉式单例

class Singleton {
private:
    static Singleton *m_singleton;
    static mutex m_mutex;
    Singleton() = default;
    Singleton(const Singleton& s) = delete; // 禁用拷贝构造函数
    Singleton& operator=(const Singleton& s) = delete;  // 禁用拷贝赋值操作符
    class GarbageCollector {
    public:
        ~GarbageCollector() {
            cout << "~GarbageCollector\n";
            if (Singleton::m_singleton) {
                cout << "free m_singleton\n";
                delete Singleton::m_singleton;
                Singleton::m_singleton = nullptr;
            }
        }
    };
    static GarbageCollector m_gc;
public:
    static Singleton* getInstance() { // 加锁的粒度大,效率较低, 对高并发的访问
        m_mutex.lock(); // 加锁,保证只有一个线程在访问下面的语句
        if (Singleton::m_singleton == nullptr){
//            std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //休眠,模拟创建实例的时间
            m_singleton = new Singleton();
        }
        m_mutex.unlock();//解锁
        return m_singleton;
    }
};
Singleton* Singleton::m_singleton = nullptr;
mutex Singleton::m_mutex;
Singleton::GarbageCollector Singleton::m_gc;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值