当前位置: 首页 > news >正文

单例模式懒汉模式和饿汉模式

线程安全
单例模式在单线程中,当然是安全的。但是如果在多线程中,由于并行判断,可能会导致创建多个实例。那么如何保证在多线程中单例还是只有一个实例呢?
常见的三种方式:

局部静态变量
原理和饿汉模式相似,利用static只会初始化一次的特性,并且在第一次调用的情况下才会被初始化。推荐使用

class Singleton {
private:
    Singleton() { };
public:
    static Singleton* getInstance() {
        static Singleton *instance = new Singleton();
        return instance;
    }
};

饿汉模式

原理:利用static,在程序编译的时候就调用构造函数实现单例,这样做的优点是保证线程安全,但是缺点就是无论后续是否用到,在编译的时候就会创建,会导致启动性能降低。
实现方法:

class Singleton_Hungry {
public:
    static Singleton_Hungry* getInstance() {
        return singleton;
    }
private:
    Singleton_Hungry() {
        cout << "Hungry creat." << endl;
    }
    static Singleton_Hungry* singleton;
};
Singleton_Hungry* Singleton_Hungry::singleton = new Singleton_Hungry();

懒汉模式

原理:利用线程锁,在获取实例的时候判断实例加上线程锁,保证判断的条件只允许一个线程操作。利用锁也可以保证单例只有一个实例。
实现方法:

#include <mutex>
std::mutex mu;
class Singleton_Lazy {
public:
     static Singleton_Lazy* getInstance() {
        if (singleton == NULL) {
            mu.lock();//打开锁
            if (singleton == NULL) {
                singleton = new Singleton_Lazy();
            }
            mu.unlock();//关闭锁
        }
        return singleton;
     }
private:
    Singleton_Lazy() {
        cout << "Lazy creat." << endl;
    }
    static Singleton_Lazy* singleton;
};
Singleton_Lazy* Singleton_Lazy::singleton = NULL;

实践验证

在linux系统上通过命令行g++ single.cpp --std=c++11 -lpthread编译

#include <iostream>
#include <mutex>
#include <thread>
#include <unistd.h>

using namespace std;
mutex mu;

class Singleton_Hungry {
public:
    static Singleton_Hungry* getInstance() {
        return singleton;
    }
private:
    Singleton_Hungry() {
        cout << "Hungry creat." << endl;
    }
    static Singleton_Hungry* singleton;
};
Singleton_Hungry* Singleton_Hungry::singleton = new Singleton_Hungry();

class Singleton_Lazy {
private:
    Singleton_Lazy() {
        cout << "Lazy creat." << endl;
    }
    static Singleton_Lazy* singleton;
public:
     static Singleton_Lazy* getInstance() {
        if (singleton == NULL) {
            //mu.lock();//打开锁
            if (singleton == NULL) {
                singleton = new Singleton_Lazy();
            }
            //mu.unlock();//关闭锁
        }
        return singleton;
     }
};
Singleton_Lazy* Singleton_Lazy::singleton = NULL;

void thr(int t) {
    cout << t << " pthread id: " << pthread_self() << endl;
    for(int i = 0; i < 3; i++) {
        Singleton_Lazy *lazy = Singleton_Lazy::getInstance();
        Singleton_Hungry *hungry = Singleton_Hungry::getInstance();
        cout << t << " lazy addr:" << lazy << endl;
        cout << t << " hungry addr:" << hungry << endl;
    }
}

int main() {
    cout<<"main process id: "<<getpid()<<endl;
    cout<<"main pthread id:"<< pthread_self()<<endl;
    thread thread1(thr, 1);
    thread thread2(thr, 2);
    thread1.join();
    thread2.join();
    return 0;
}

结果分析

结果和预想一致,饿汉模式在程序编译阶段调用构造函数,懒汉模式在调用的时候创建,如果不加线程锁会导致创建多个实例。

【C++】保证线程安全的单例模式_c++ 线程安全单例模式-CSDN博客

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 2024年【甘肃省安全员B证】考试资料及甘肃省安全员B证模拟试题
  • 探索 SPL-404 协议标准:NFT 与 DeFi 的融合
  • spring框架实现滑动验证码功能
  • Java修炼 Java SE 面试题目 (简答) 2024.7.26 22:16
  • .net core docker部署教程和细节问题
  • 安防视频监控EasyCVR视频汇聚平台修改配置后无法启动的原因排查与解决
  • Java 扫雷游戏
  • Java:swagger/knife4j接口返回的json数据中文显示乱码问号???
  • OpenAI发布GPT-4 Mini的深度分析及中国大模型的弯道超车机会
  • 【Golang 面试基础题】每日 5 题(十)
  • 基于上云api前端开发经验教训(loading...)
  • 基于python的BP神经网络回归模型
  • RT-Thread Studio搭建 Renesa Version Board开发环境
  • Python 中数据科学和机器学习的作用
  • 如何在 SpringBoot 中优雅的做参数校验?
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 78. Subsets
  • avalon2.2的VM生成过程
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • CSS实用技巧干货
  • HTTP请求重发
  • Java方法详解
  • js正则,这点儿就够用了
  • js中forEach回调同异步问题
  • leetcode378. Kth Smallest Element in a Sorted Matrix
  • Node + FFmpeg 实现Canvas动画导出视频
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 从输入URL到页面加载发生了什么
  • 对JS继承的一点思考
  • 多线程 start 和 run 方法到底有什么区别?
  • 给Prometheus造假数据的方法
  • 关于字符编码你应该知道的事情
  • 机器学习学习笔记一
  • 今年的LC3大会没了?
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶
  • 说说动画卡顿的解决方案
  • 通过git安装npm私有模块
  • 用jQuery怎么做到前后端分离
  • 用mpvue开发微信小程序
  • 主流的CSS水平和垂直居中技术大全
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ${factoryList }后面有空格不影响
  • (1)(1.13) SiK无线电高级配置(五)
  • (10)Linux冯诺依曼结构操作系统的再次理解
  • (el-Transfer)操作(不使用 ts):Element-plus 中 Select 组件动态设置 options 值需求的解决过程
  • (MATLAB)第五章-矩阵运算
  • (第27天)Oracle 数据泵转换分区表
  • (二)Kafka离线安装 - Zookeeper下载及安装
  • (附源码)springboot家庭财务分析系统 毕业设计641323
  • (南京观海微电子)——I3C协议介绍
  • (十六)Flask之蓝图
  • (四)库存超卖案例实战——优化redis分布式锁
  • (未解决)jmeter报错之“请在微信客户端打开链接”