Skip to content

设计模式

单例模式的双锁分别有什么作用

实现单例设计模式(懒汉,饿汉)

单例模式详细:链接

singleton-how-should-it-be-used

  • 意图:保证一个类仅有一个实例,并提供一个访问他的全局访问点。
  • 主要解决:一个全局使用的类频繁的创建与销毁。
  • 何时使用:当您想控制实例数目节省系统资源的时候。
  • 如何解决:判断系统是否已经有这个单例,如果有则返回,如果没有则创建。
  • 关键代码:构造函数是私有的。

饿汉:在类加载时就创建实例;懒汉:在第一次使用时进行实例化

cpp
class Singleton
{
  private:
    static Singleton instance;
  private:
    Singleton();
    ~Singleton();
    Singleton(const Singleton&);
    Singleton& operator=(const Singleton&);
  public:
    static Singleton& getInstance() {
      return instance;
    }
}

// initialize defaultly
Singleton Singleton::instance;

简述常见的工厂模式以及单例模式的使用场景

如何实现单例模式?如何避免发生对象的用户复制行为?如何实现线程安全的单例模式?DCLP是什么,有什么问题?

  • 将构造函数、析构函数、复制构造函数、赋值操作符声明为私有,即可实现单例模式 单例模式实现代码通常为:

    cpp
    class Singleton
    {
    public:
        static Singleton* Instance();
    protected:
        Singleton();
    private:
        static Singleton* _instance;
    };
    Singleton::Singleton(){}
    Singleton* Singleton::_instance = nullptr;
    Singleton* Singleton::Instance()
    {
        if(_instance == nullptr)
        _instance = new Singleton;
        return _instance;
    }
  • 避免用户的复制行为,可以将复制构造函数声明为private或者使用C++11中的delete语法。

  • 实现线程安全的单例模式:上面实现中的GetInstance()不是线程安全的,因为在单例的静态初始化中存在竞争条件。如果碰巧有多个线程在同时调用该方法,那么就有可能被构造多次。

    比较简单的做法是在存在竞争条件的地方加上互斥锁。这样做的代价是开销比较高。因为每次方法调用时都需要加锁。
    比较常用的做法是使用双重检查锁定模式(DCLP) 。但是DCLP并不能保证在所有编译器和处理器内存模型下都能正常工作。如,共享内存的对称多处理器通常突发式提交内存写操作,这会造成不同线程的写操作重新排序。这种情况通常可以采用volatile解决,他能将读写操作同步到易变数据中,但这样在多线程环境下仍旧存在问题。

手写生产者消费者模型

吃好喝好 快乐地活下去