设计模式——单例模式

单例模式的知识点

  • 单例模式的为什么这么写?
  • 单例模式中的构造函数为什么是private?
  • instance为什么是static?
  • 如何获取单例?
  • 什么是懒汉模式?
  • 懒汉模式存在的问题?如何解决?
  • 饿汉模式?

首先,构造函数是private是要保证单例,如果是public自然是可以初始化多个对象的;
其次,instance是static的原因是成员表示类的实例而不是属于类的各个对象;
从而,private+static保证了我们获取对象的唯一性;
再次,还需要一个获取这个单例的入口,就是getInstance,从这个接口里面返回单例。

// 线程不安全的单例模式(懒汉模式)
class SingleClass{
  public:
    static SingleClass* getInstance(){
      if(instance == nullptr){
        instance = new SingleClass();
        cout<<"创建了一个单例模式对象 @" << instance <<endl;
      }
      return instance;
    }
  private:
    static SingleClass* instance;
    SingleClass(){};
};

// 初始化静态成员变量
SingleClass* SingleClass::instance = nullptr;
int main()
{
	SingleClass* s1 = SingleClass::getInstance();
	SingleClass* s2 = SingleClass::getInstance(); 
	return 0;
}
//在这种“懒汉式”单例模式中,存在的线程不安全问题主要是当多个线程同时检测到instance == nullptr时,它们都可能尝试创建该对象实例。结果,你可能会结束得到多个SingleClass对象实例,违反了单例模式的设计原则。


// 线程安全的单例模式(懒汉模式)
  public:
    static SingleClass* getInstance(){
      if(instance == nullptr){
	    // 创建实例之前加锁
	    mtx.lock();
        if(instance == nullptr)
        {
			 // 再判断一次,确保不会因为加锁期间多个线程同时进入
	        instance = new SingleClass();
        }
        // 解锁
        mtx.unlock();
      }
      return instance;
    }
  private:
    static SingleClass* instance;
    SingleClass(){};
	static mutex mtx;
};

// 初始化静态成员变量
SingleClass* SingleClass::instance = nullptr;
mutex SingleClass::mtx;

int main()
{
	SingleClass* s1 = SingleClass::getInstance();
	SingleClass* s2 = SingleClass::getInstance(); 
	return 0;
}
// 1 两个if的原因:如果没有第二个if则当第一个线程释放锁时,下一个线程加锁则又会创建一个新的单例对象,违背单例的原则
// 2 为什么不在第一个if上加锁,若在第一个if之前加锁每次调用getInstance()函数时,都会进行锁操作,即使单例对象已经创建了。锁操作相对来说是昂贵的,特别是在高并发环境下。高并发环境下很多线程同时调用getInstance(),会对锁产生竞争,不得不等待锁的释放,从而逐渐退化为单线程模式

最后是饿汉模式,与懒汉模式不同的是类一加载就实例化对象,即在执行main函数之前就有了对象,这样在getInstance函数里面不用再去new instance,直接return instance

 public:
    static SingleClass* getInstance(){
      return instance;
    }
  private:
    static SingleClass* instance;
    SingleClass(){};
	static mutex mtx;
};
SingleClass* SingleClass::instance = new SingleClass();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值