美文网首页
C++懒汉式单例模式遇到多线程

C++懒汉式单例模式遇到多线程

作者: 突击手平头哥 | 来源:发表于2019-10-12 22:19 被阅读0次

C++懒汉式单例模式遇到多线程

单例模式是一个创建型设计模式, 就是保证在整个程序运行中仅存在该类的一个实例, 比如数据库句柄/日志等.

单例模式要求

  • 1 构造函数必须私有, 防止使用new的方式初始化
  • 2 拷贝构造函数和赋值操作必须私有, 避免赋值创建
  • 3 提供一个static类型的函数作为对外接口, 负责获取对象

懒汉式

懒汉式的意思是知道我第一次使用该实例的时候才会去初始化它, 如果从未使用就不初始化。
但是在多线程中使用懒汉式, 必然存在问题

懒汉式单例模式的实现

  • 1 使用静态变量
// 局部静态变量
class Singleton{
public:
    // 返回指针避免拷贝复制
    static Singleton* getInstance(){
        static Singleton instance;
        return &instance;
    }
private:
    /*避免new方法和赋值操作*/
    Singleton(){}
    Singleton(Singleton const & single);
    Singleton& operator = (const Singleton& single);
};

注意:多线程中局部静态变量初始化并不保证线程安全
如果按如上写法, 那么只有一个办法就是加锁, 而且必然是很粗暴的上下加锁的一种

  • 2 普通实现
class Singleton{
public:
    static Singleton* getInstatce(){
          if( NULL == lazy ){
                 lazy = new Singleton;
          }
          return lazy;
    }
private:
    static Singleton* lazy;
    Singleton(){}
    Singleton(Singleton const & single);
    Singleton& operator = (const Singleton& single);
};
//类静态变量必须外部初始化
Singleton* Singleton::lazy = NULL;

同样存在多线程的问题, 但是加锁的方式可以优化一下, 因为可以先进行一下判断在加锁

ps:如果采用指针的方式, 那么必须注意释放的问题

完整实现(包括加锁和最后的资源释放)

class Singleton{
public:
    typedef std::shared_ptr<Singleton> Ptr;
    static Ptr get_instance(){
        if(m_instance_ptr==nullptr){
            std::lock_guard<std::mutex> lk(mutex);
            if(m_instance_ptr == nullptr){
              m_instance_ptr = std::shared_ptr<Singleton>(new Singleton);
            }
        }
        return m_instance_ptr;
    }

private:
    Singleton(){}
    Singleton(Singleton const & single);
    Singleton& operator = (const Singleton& single);
    static Ptr m_instance_ptr;
    static std::mutex mutex;
};

// 初始话静态变量
Singleton::Ptr Singleton::m_instance_ptr = nullptr;
std::mutex Singleton::mutex;
  • 只有在最开始调用时, 才会出现m_instance_ptrnull, 之后永远有值则不用加锁, 能够极大的优化效率
  • 通过智能指针的方式, 实现资源释放(起始只有进程退出时才需要释放资源, 如果要求不高可以直接系统回收)

扩展:

  • 如果不使用智能指针的方式, 可以创建初始化一个静态成员类, 在该成员析构时, delete对象
class Singleton{
public:
    static Singleton* getInstatce(){
          if( NULL == m_instance ){
                 std::lock_guard<std::mutex> lock(mutex);
                 if( NULL == m_instance ){
                       m_instance = new Singleton;
                 }
          }
          return m_instance;
    }
private:
    Singleton(){}
    Singleton(Singleton const & single);
    Singleton& operator = (const Singleton& single);

    static Singleton* m_instance;
    static mutex mutex;

    class GC
     {
     public :
         ~GC()
         {
             // 销毁所有资源
             if (m_Instance != NULL )
             {
                 delete m_instance;
                 m_instance = NULL ;
             }
         }
     };
     static GC gc;
};
//类外初始化
Singleton* Singleton::m_instance = NULL;
std::mutex Singleton::mutex;
Singleton::GC Singleton::gc;

可以通过初始化一个私有的静态变量的的方式, 在最后析构时调用函数释放单例的资源

相关文章

  • 单例模式Java篇

    单例设计模式- 饿汉式 单例设计模式 - 懒汉式 单例设计模式 - 懒汉式 - 多线程并发 单例设计模式 - 懒汉...

  • C++懒汉式单例模式遇到多线程

    C++懒汉式单例模式遇到多线程 单例模式是一个创建型设计模式, 就是保证在整个程序运行中仅存在该类的一个实例, 比...

  • kotlin实现单例模式

    1.懒汉式实现单例模式 2.线程安全懒汉式实现单例模式 3.双重校验懒汉式实现单例模式 4.静态内部类方式实现单例模式

  • Singleton 单例模式

    饿汉式单例模式 饿汉式单例模式 通过静态代码块增加异常处理 懒汉式单例模式 存在线程安全问题 懒汉式单例模式 解决...

  • 单例(Singleton)

    单例设计模式 单例模式的创建 饿汉式1 饿汉式2 懒汉式 优化后的懒汉式(线程安全): 饿汉式与懒汉式区别 单例模...

  • 2018-05-14

    单利设计模式 懒汉式 单例模式 饿汉式 单利模式 懒汉式与饿汉式的区别: 双重锁式 单例模式 (DCL )

  • 单例模式

    单例,全局只有一个实例 单例模式可以分为懒汉式和饿汉式: 懒汉式单例模式:在类加载时不初始化。 饿汉式单例模式:在...

  • 第3章 创建型模式-单例模式

    ■ 饿汉式单例类 ■ 懒汉式单例类 ■ 单例模式的实例

  • 12、彻底玩转单例模式

    饿汉式单例: 懒汉式单例: 问题: 懒汉式在多线程下: 结果:(可能会出现多次创建对象——即和单例相违背) 双重检...

  • 大话设计模式之_单例模式

    大话设计模式之___单例模式 什么是单例模式单例模式有哪些(会顺带讲些懒汉式的性能优化)懒汉式与饿汉式的区别 什么...

网友评论

      本文标题:C++懒汉式单例模式遇到多线程

      本文链接:https://www.haomeiwen.com/subject/xgbcmctx.html