c++设计模式-单例模式

定义
只提供唯一一个类的实例,具有全局变量的特点,在任何位置都可以通过接口获取到那个唯一实例
具体运用场景
1.设备管理器,系统中可能有多个设备,但是只有一个设备管理器,用于管理设备驱动;
2.数据池,用来缓存数据的数据结构,需要在一处写,多处读取或者多处写,多处读取;
要点
1.全局只有一个实例:static 特性,同时禁止用户自己声明并定义实例(把构造函数设为 private)
2.禁止赋值和拷贝
3.用户通过接口获取实例:使用 static 类成员函数
4.线程安全
实现
示例一、没有考虑线程安全的方式

class Singleton{
private:
    Singleton(){
        //......
    }
    Singleton(Singleton&);
    Singleton& operator=(const Singleton&);
    static Singleton* instance_ptr;
public:
    ~Singleton(){
        //.....
    }
    static Singleton* get_instance(){
        if(instance_ptr==nullptr){
              instance_ptr = new Singleton;
        }
        return instance_ptr;
    }
};

Singleton* Singleton::instance_ptr = nullptr;

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

线程安全:上述中,可能会造成多个线程对共享内存数据访问的竞争条件的形成:即,第一个线程在访问if语句时判断instance_ptr为空,开始实例化单例。同时,第二个线程访问单例,判断到if还是为空,也开始实例化单例。

C++标准中对数据竞争的定义是:多个线程并发的去修改一个独立对象,数据竞争是未定义行为的起因。

内存泄漏:这个类没有负责delete对象,需要使用者自己delete,因此存在内存泄漏的风险。
示例二、线程安全的方式

//include<mutex>
class Singleton{
private:
    Singleton(){
        //......
    }
    Singleton(Singleton&);
    Singleton& operator=(const Singleton&);
    static Singleton* instance_ptr;
    static std::mutex m_mutex;
public:
    ~Singleton(){
        //.....
    }
    static Singleton* get_instance(){
        if(instance_ptr==nullptr){
            std::lock_guard<std::mutex> lk(m_mutex);
            if(instance_ptr==nullptr) {
                instance_ptr = new Singleton;
            }
        }
        return instance_ptr;
    }
};
// init static member
Singleton* Singleton::instance_ptr = nullptr;

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

加锁,这里使用了两个 if判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁,避免每次调用 get_instance都加锁。

互斥:是指散布在不同进程之间的若干程序片断,当某个进程运行其中一个程序片段时,其它进程就不能运行它们之中的任一程序片段,只能等到该进程运行完这个程序片段后才可以运行。如果用对资源的访问来定义的话,互斥某一资源同时只允许一个访问者对其进行访问,具有唯一性和排它性。但互斥无法限制访问者对资源的访问顺序,即访问是无序的。

看起来很美好,但这样是有问题的,在某些平台,双重检查锁定模式会失效!具体可以看这篇文章
示例三、c++11中的静态局部变量的线程安全

class Singleton{
private:
    Singleton(){
        //......
    }
    Singleton(Singleton&);
    Singleton& operator=(const Singleton&);
public:
    ~Singleton(){
        //.....
    }
    static Singleton& get_instance(){
        static Singleton instance;
        return instance;
    }
};

这种方法叫做 Meyers' Singleton ,是Meyers提出的。所用到的特性是在C++11标准中的Magic Static特性:
如果当变量在初始化的时候,并发同时进入声明语句,并发线程将会阻塞等待初始化结束。

原文链接: https://www.cnblogs.com/Redwarx008/p/12235125.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    c++设计模式-单例模式

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/324983

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月1日 下午3:09
下一篇 2023年3月1日 下午3:09

相关推荐