线程安全的单例模式

本文介绍了设计模式中的单例模式,分为饿汉模式和懒汉模式。饿汉模式在程序初始化时即完成资源申请,不考虑线程安全。而懒汉模式在首次调用时才初始化,可能存在线程安全问题,因此需要通过加锁来保护资源创建。总结了实现懒汉模式的五个关键步骤,包括使用static修饰、延迟加载、volatile关键字、线程安全的加锁保护以及二次判空优化效率。
摘要由CSDN通过智能技术生成

何为单利模式和设计模式
单例模式:就是是一经典的、常见的、常考的设计模式
设计模式:根据一些经典常见的场景,给定了一些解决办法,这就是设计模式

分类
饿汉模式(空间换时间)不考虑线程安全问题—>在程序初始化阶段就完成资源申请初始化

代码!!!!

template <typename T>
class Singleton {
 static T data;
public:
 static T* GetInstance() {
  return &data;
}
};

懒汉模式(时间换空间)

template <typename T>
class Singleton {
 static T* inst;
public:
 static T* GetInstance() {
  if (inst == NULL) {
   inst = new T();
 }
  return inst;
}
};

存在线程不安全缺陷,第一次调用GetInstance时候,如果两个线程同时调用,可能会创建出两份T对象实例化。但是后续再次调用就没有问题。

所以进行了改进:
考虑线程安全问题,在资源申请前进行了加锁保护。

// 懒汉模式, 线程安全
template <typename T>
class Singleton {
 volatile static T* inst;  // 需要设置 volatile 关键字, 否则可能被编译器优化.
 static std::mutex lock;
public:
 static T* GetInstance() {
  if (inst == NULL) {   // 双重判定空指针, 降低锁冲突的概率, 提高性能.
   lock.lock();      // 使用互斥锁, 保证多线程情况下也只调用一次 new.
   if (inst == NULL) {
    inst = new T();
  }
   lock.unlock();
 }
  return inst;
}
};

总结一下,懒汉模式实现的五个步骤
1.保证内存中资源只有一份—>使用static修饰
2.使用时再去加载资源初始化—>定义的时候并不直接定义对象,而是定义指针,访问的时候为NULL则new一个资源
3.防止编译器过度优化—>使用volatile关键字修饰
4.考虑线程安全问题,在资源申请及判断前加锁保护(防止多线程访问资源被new了多次)
5.需要考虑效率问题:资源已经加载初始化,后期获取操作句柄时,每次都要加锁解锁两次,并且多执行同时访问还有可能造成冲突,使用二次判空来解决。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值