【C++】线程安全的单例模式:饿汉方式、懒汉方式

单例模式是一种非常经典的设计模式,一个类在内存中只能实例化一个对象,资源在内存中只能有一份,提供一个统一的接口进行访问。
要实现单例模式可以采用两种方式:饿汉方式、懒汉方式。

  • 饿汉方式:在程序的初始化阶段完成资源的申请加载初始化以及对象的实例化,可以将其看作是一个吃完饭立马洗碗的饿汉,因为这样下一次吃饭时就可以直接端起碗吃饭,这种方式的思想是以空间换时间。例如市面上的大型手游王者荣耀就采用的是这种思想,在游戏开始之前初始化完所有资源,在游戏进行中就避免了再去加载资源,保持游戏的流畅度。
    用饿汉方式来实现单例模式:通过 Singleton 这个包装类来使用 T 对象, 则一个进程中只有一个 T 对象的实例。
template <typename T> 
class Singleton {
    
      
    static T data; 
    public:  static T* GetInstance() {
    
        
    return &data;
         } 
      }; 
  • 懒汉方式:资源在使用时才申请加载初始化,可以将其看作一个吃完饭不洗碗的懒汉,在下一次吃饭之前再去洗碗,这是延迟加载的思想。例如支付宝就采用的是这种思想,支付宝中各类模块很多,但为了保证打开的速度够快,所以在打开时只加载使用模块的资源,并不去初始化别的模块资源,优化服务器的启动速度。
    用懒汉方式来实现单例模式:要注意双重 if 判定, 避免不必要的锁竞争,还要使用volatile关键字防止过度优化。
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;
   } 
   };

猜你喜欢

转载自blog.csdn.net/weixin_45177279/article/details/115286562