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

单例模式

    • 普通的非单例模式
    • 饿汉
    • 懒汉

  • 单例模式是设计模式的一种,一个对象/资源只能被初始化加载一次(比如游戏中的图片资源)
    实现方式:饿汉懒汉

普通的非单例模式

#include 
#include 

class singleton{
     
  public:
    int _data;
    int *get_instance(){
     
      return &_data;
    }
};

int main()
{
     
  singleton a1, a2;
  a1._data = 10;
  a2._data = 20;

  printf("a1 : %d - %p\na2 : %d - %p\n", a1._data, a1.get_instance(), a2._data, a2.get_instance());
  return 0;
}

饿汉

  • 所有资源在程序初始化阶段一次性完成初始化
#include 
#include 

class singleton{
     
  public:
    static int _data; // 所有实例化的对象共用同一个资源
    int *get_instance(){
     
      return &_data;
    }
};

int singleton::_data = 100; // 程序初始化阶段完成资源的加载以及初始化

int main()
{
     
  singleton a1, a2;
  printf("a1 : %d - %p\na2 : %d - %p\n", a1._data, a1.get_instance(), a2._data, a2.get_instance());
  a1._data = 10;
  a2._data = 20;

  printf("a1 : %d - %p\na2 : %d - %p\n", a1._data, a1.get_instance(), a2._data, a2.get_instance());
  return 0;
}

懒汉

  • 资源在使用的时候进行初始化,会涉及到线程安全问题(volatile / static / mutex / 二次判断
  • 使用static帮助多个对象使用同一份空间资源
  • 加锁保护资源申请过程,实现线程安全
  • 在加锁之外进行二次判断,减少锁冲突概率,提高效率
  • volatile防止编译器过度优化,每次判断都为NULL的情况
#include 
#include 
#include 

std::mutex lock;
class singleton{
     
  public:
    volatile static int *_data; // 所有实例化的对象共用同一个资源;防止编译器过度优化
    volatile int *get_instance(){
      // volatile修饰函数返回值
      if(_data == NULL){
      // 二次判断,减少锁冲突
        lock.lock();
        if(_data == NULL){
      // 判断与申请资源存在线程安全问题
         _data = new int;
        }
      }
      lock.unlock();
      return _data;
    }
};

volatile int *singleton::_data = nullptr; // _data被volatile修饰

int main()
{
     
  singleton a1, a2;
  printf("a1 : %d - %p\na2 : %d - %p\n", *a1._data, a1.get_instance(), *a2._data, a2.get_instance());
  *a1._data = 10;
  *a2._data = 20;

  printf("a1 : %d - %p\na2 : %d - %p\n", *a1._data, a1.get_instance(), *a2._data, a2.get_instance());

  return 0;
}

你可能感兴趣的:(设计模式,c++,多线程)