【Linux】单例模式 — 饿汉与懒汉

什么是单例模式

单例模式是一种经典的,常用的。常考的设计模式。
设计模式:大佬们针对一些经典的常见场景,给定一些对应的解决方案

什么是饿汉?什么是懒汉?

概念不太好理解,我举个例子大家应该就能明白了

这里是个洗碗的例子。
第一种:吃完饭立刻洗碗因为下顿饭好了的时候可以立即吃到饭,这是饿汉方式:时刻准备着
第二种:吃完饭把碗放下,等吃下顿饭的时候再去洗碗,这是懒汉方式:用的时候再准备

有没有发现二者的区别呢?没错,懒汉模式的核心思想是“延时加载”,从而能够优化服务器的启动速度。
这与我们之前在线程讲过的写实拷贝有异曲同工之妙,因为写实拷贝也提高了创建子进程的速度。

饿汉方式实现单例模式

template<typename T>
class Singleton{
  static T data;   //提前准备好数据
  public:
  static T* GetInstance()
  {
    return &data;
  }
};

通过上面Singleton这个被包装好的类,我们在一个进程中只能有一个T对象的实例。

懒汉方式实现单例模式

template<typename T>
class Singleton{
  static T* inst;
  public:
  static T* GetInstance()
  {
    if(inst==NULL)
    {
      inst=new T(); //用的时候才new一个对象
    }
    return inst;
  }
};

但是这里存在一个严重的问题:线程不安全!!
因为在第一次调用的时候,如果被两个线程同时调用则可能会创建出两份T对象的实例,不符合单例模式的要求。但是后续调用不会有问题。
这里我做出修改如下:

线程安全版:懒汉模式

template<typename T>
class Singleton{
 volatile static T* inst;  //防止被编译器优化
 static std::mutex lock;
  public:
  static T* GetInstance()
  {
    if(inst==NULL)   //双重判断降低锁冲突的概率,提高性能
    {
      lock.lock();
      if(inst==NULL)
      inst=new T(); //用的时候才new一个对象
      lock.unlock();
    }
    return inst;
  }
};

注意事项:

  1. 加锁解锁的位置
  2. 双重if 判断,可以减少锁的消耗,避免不必要的锁竞争
  3. volatile 关键字保持内存可见性,防止编译器过度优化

Linux的内容,基本到这里就告一段落了,其他内容我在前面的博客也讲到了,有需要的小伙伴可以在我的专栏里查看。。
下篇博客博主准备总结网络相关知识了,不要忘记关注博主哦~

猜你喜欢

转载自blog.csdn.net/ly_6699/article/details/98471185