线程安全的单例模式:饿汉模式&懒汉模式

简介: 线程安全的单例模式:饿汉模式&懒汉模式

一、单例模式


单例模式:一种典型的设计模式。


应用场景:


       一个类只能实例化一个对象,向外提供统一访问接口的场景。


作用:


       对资源进行统一管理,以及避免数据在不同对象中出现不同的体现。


两种实现:饿汉模式&懒汉模式


二、饿汉模式


1.特点


       资源静态化。


       在程序初始化阶段,完成对象的实例化。


       以空间换时间的思想,在使用的时候就可以直接使用。


优点:


       在构造对象时,不需要考虑线程安全问题。


缺点:


       初始化速度慢。


2.实现关键


1)如何在程序初始化阶段完成对象的实例化


       解决方法:在类中定义唯一的对象,且用static修饰对象


2)如何让一个类只能有一个对象


       解决方法:私有化构造函数


3.代码实现


#include<iostream>
class Singleton {
  private:
    int _data;
    static Singleton _eton;
    Singleton () : _data(0) {}
  public:
    static Singleton *GetInstance() {
      return &_eton;
    }
    int *GetData() {
      return &_data;
    }
};
Singleton Singleton::_eton;
int main() {
  std::cout << Singleton::GetInstance() -> GetData() << std::endl;
  return 0;
}


三、懒汉模式


1.特点


       对象在访问使用的时候才去实例化。


       一种延迟加载的思想,用的时候再去加载,节省资源。


优点:


       初始化速度快。


缺点:


       在构造对象时,需要考虑线程安全问题。


2.实现关键


1)如何在访问使用的时候采取实例化对象


       解决方法:在类中定义唯一的对象指针,且用static修饰


2)如何让一个类只能有一个对象


       解决方法:私有化构造函数


总结:


       1.定义静态对象指针;


       2.构造函数私有化;


       3.加锁保护对象构造过程;


       4.double check提高效率;


       5.volatile关键字修饰,防止编译器过度优化。


3.代码实现


#include<iostream>
#include<mutex>
class Singleton {
  private:
    int _data;
/*volatile*/static Singleton *_eton;//c语言实现时,需要加上volatile关键字,保持_eton内存可见性,防止编译器过度优化
    static std::mutex _mutex;
    Singleton() {}
  public:
    static Singleton *GetInstance(){
      if (_eton == NULL) {//双层检测,降低锁冲突概率
        _mutex.lock();//加锁,确保线程安全
        if (_eton == NULL) {
          _eton = new Singleton();
        }
        _mutex.unlock();
      }
      return _eton;
    }
    int *GetData() {
      return &_data;
    }
};
Singleton* Singleton::_eton = NULL;
std::mutex Singleton::_mutex;
int main() {
  std::cout << Singleton::GetInstance() -> GetData() << std::endl;
  return 0;
}
相关文章
|
20天前
|
安全 Java 关系型数据库
单例模式下引发的线程安全问题
单例模式确保类在进程中仅有一个实例,适用于如数据库连接等场景。分为饿汉式与懒汉式:饿汉式在类加载时创建实例,简单但可能浪费资源;懒汉式延迟创建实例,需注意线程安全问题,常采用双重检查锁定(Double-Checked Locking)模式,并使用 `volatile` 关键字避免指令重排序导致的问题。
42 2
单例模式下引发的线程安全问题
|
3月前
|
设计模式 安全 Java
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
Java面试题:设计模式如单例模式、工厂模式、观察者模式等在多线程环境下线程安全问题,Java内存模型定义了线程如何与内存交互,包括原子性、可见性、有序性,并发框架提供了更高层次的并发任务处理能力
64 1
|
2月前
|
设计模式 SQL 安全
单例模式大全:细说七种线程安全的Java单例实现,及数种打破单例的手段!
设计模式,这是编程中的灵魂,用好不同的设计模式,能使你的代码更优雅/健壮、维护性更强、灵活性更高,而众多设计模式中最出名、最广为人知的就是Singleton Pattern单例模式。通过单例模式,我们就可以避免由于多个实例的创建和销毁带来的额外开销,本文就来一起聊聊单例模式。
|
3月前
|
微服务
多线程内存模型问题之在单例模式中,volatile关键字的作用是什么
多线程内存模型问题之在单例模式中,volatile关键字的作用是什么
|
3月前
|
设计模式 安全 Java
Java面试题:解释单例模式的实现方式及其优缺点,讨论线程安全性的实现。
Java面试题:解释单例模式的实现方式及其优缺点,讨论线程安全性的实现。
25 0
|
3月前
|
设计模式 安全 NoSQL
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
Java面试题:设计一个线程安全的单例模式,并解释其内存占用和垃圾回收机制;使用生产者消费者模式实现一个并发安全的队列;设计一个支持高并发的分布式锁
45 0
|
3月前
|
设计模式 安全 Java
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
Java面试题:如何实现一个线程安全的单例模式,并确保其在高并发环境下的内存管理效率?如何使用CyclicBarrier来实现一个多阶段的数据处理任务,确保所有阶段的数据一致性?
46 0
|
3月前
|
存储 设计模式 监控
Java面试题:如何在不牺牲性能的前提下,实现一个线程安全的单例模式?如何在生产者-消费者模式中平衡生产和消费的速度?Java内存模型规定了变量在内存中的存储和线程间的交互规则
Java面试题:如何在不牺牲性能的前提下,实现一个线程安全的单例模式?如何在生产者-消费者模式中平衡生产和消费的速度?Java内存模型规定了变量在内存中的存储和线程间的交互规则
38 0
|
3月前
|
设计模式 安全 NoSQL
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
Java面试题:结合单例模式与Java内存管理,设计一个线程安全的单例类?分析Java多线程工具类ExecutorService与Java并发工具包中的工具类,设计一个Java并发框架的分布式锁实现
45 0
|
3月前
|
设计模式 存储 缓存
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
Java面试题:结合单例模式与Java内存模型,设计一个线程安全的单例类?使用内存屏障与Java并发工具类,实现一个高效的并发缓存系统?结合观察者模式与Java并发框架,设计一个可扩展的事件处理系统
27 0