设计模式-单例模式(懒汉+饿汉+线程安全模式)

目录

单例模式

单例模式可以说是23种设计模式中最为简单的一种设计模式

  1. 类中只有唯一一个实例并且是私有化的,只能通过公有的静态函数获取,并且构造函数私有化,防止被外部实例化
  2. 提供静态的公有函数用来获取访问唯一的一个实例

如果说类中的某一个资源是属于类本身的,而不是所属类的某一个对象的,我们就可以把这个资源设置为static, 类比来说,如果某一个类的成员都是所属于类本身,并且要公共使用的话,我们就可以把这个类设置为单例模式,并且提供唯一的static实例 公共使用

使用场景:常用于数据库类,日志类的实现

最简单的单例模式类:

复制代码
class single{
 private:
     //私有静态指针变量指向唯一实例
     static single *p;
 
     //私有化构造函数
    single(){}
    ~single(){}

public:
    //公有静态方法获取实例
    static single* getinstance();
};

懒汉模式

单例模式类中有唯一一个实例的指针,懒汉模式,即第一次使用时才初始化这个单例模式的指针

复制代码
class single{
 private:
     //私有静态指针变量指向唯一实例
     static single *p;
 
     //私有化构造函数
    single(){}
    ~single(){}

public:
    //公有静态方法获取实例
    static single* getinstance();
};

single* single::p = NULL;
single* single::getinstance(){
        if (NULL == p){
            p = new single;  
        }
    return p;
}

在调用getinstance函数获取唯一实例的时候才进行第一次初始化.

饿汉模式

饿汉模式顾名思义非常饿,它是在程序一开始的时候,就对唯一的实例初始化了

复制代码
class single{
 private:
     //私有静态指针变量指向唯一实例
     static single *p;
 
     //私有化构造函数
    single(){}
    ~single(){}

public:
    //公有静态方法获取实例
    static single* getinstance();
};
single* single::p = new single();
single* single::getinstance(){
    return p;
}

线程安全的懒汉模式

之前的懒汉模式并没有提到多线程安全的情况,如果现在有多个线程使用单例模式类,就有可能会导致多个线程对该实例的多次初始化,这就产生错误了,接下来给出线程安全版本

双重检查锁定(过时,错误的版本)

复制代码
class single{
 private:
     //私有静态指针变量指向唯一实例
    static single *p;
    
    static pthread_mutex_t lock;//定义一个互斥锁
     //私有化构造函数
    single(){
          pthread_mutex_init(&lock, NULL);
    }
    ~single(){}

public:
    //公有静态方法获取实例
    static single* getinstance();
};

pthread_mutex_t single::lock;

single* single::p = NULL;
single* single::getinstance(){
    if (NULL == p){
        pthread_mutex_lock(&lock);
        if (NULL == p){
            p = new single;
        }
        pthread_mutex_unlock(&lock);
    }
    return p;
}

这种保证线程安全的方式叫做双重检查锁定,使用互斥锁对new进行保护,又为了防止每次调用函数时都需要加锁,在锁的外围又加了一层 if判断,但是这种做法后来被证实是错误的,并不能完全保证线程安全

详细参考Scott Meyers 与 Andrei Alexandrescu 的"C++ and the Perils of Double-Checked Locking"这篇文章

C++11 特有的线程安全懒汉模式

复制代码
 class single{
 private:
     single(){}
     ~single(){}
 
 public:
     static single* getinstance();
 };

single* single::getinstance(){
   static single obj;
   return &obj;
}

这种方式不需要加互斥锁,也能保护线程安全,算是最好的一种实现方式.

复制代码
 class single{
 private:
     single(){}
     ~single(){}
     
 void my_print_private()
 { 
    cout<<"helloworld"<<endl;
 }
 
 public:
     static single* getinstance();
     
     static void my_print_public()  //这里也可以改成不是static,函数体直接调用my_print_private即可
     {
          single::getinstance()->my_print_private();
     }
 };

single* single::getinstance(){
   static single obj;
   return &obj;
}
相关推荐
七月丶7 小时前
别再手动凑 PR 了:这个 AI Skill 会按仓库习惯自动建分支、拆提交、提 PR
人工智能·设计模式·程序员
刀法如飞7 小时前
从程序员到架构师:6大编程范式全解析与实践对比
设计模式·系统架构·编程范式
九狼7 小时前
Flutter + Riverpod +MVI 架构下的现代状态管理
设计模式
静水流深_沧海一粟1 天前
04 | 别再写几十个参数的构造函数了——建造者模式
设计模式
StarkCoder1 天前
从UIKit到SwiftUI的迁移感悟:数据驱动的革命
设计模式
阿星AI工作室1 天前
给openclaw龙虾造了间像素办公室!实时看它写代码、摸鱼、修bug、写日报,太可爱了吧!
前端·人工智能·设计模式
_哆啦A梦2 天前
Vibe Coding 全栈专业名词清单|设计模式·基础篇(创建型+结构型核心名词)
前端·设计模式·vibecoding
阿闽ooo5 天前
中介者模式打造多人聊天室系统
c++·设计模式·中介者模式
小米4965 天前
js设计模式 --- 工厂模式
设计模式
逆境不可逃5 天前
【从零入门23种设计模式08】结构型之组合模式(含电商业务场景)
线性代数·算法·设计模式·职场和发展·矩阵·组合模式