单例模式

https://media.githubusercontent.com/media/irisHYT/ImageHosting0/main/images/IMG_20201003_180559.webp

单例模式

程序中只存在一个单独的对象,单例模式的写法分为两种:

  • 懒汉模式: 在使用的时候才创建。
  • 饿汉模式: 在程序启动时就创建。

懒汉模式

 1#define sync() __asm__ volatile ("lwsync")
 2
 3class Instance {
 4    public:
 5        static Instance* GetInstance() {
 6            if (!_inst) {
 7                _mtx.Lock();
 8                if (!_inst) {
 9                    Instance* t = new Instance;
10                     sync();
11                    _inst = t;
12                }
13                _mtx.Unlock();
14            }
15
16            return _inst;
17        }
18    
19    private:
20        Instance();
21        Instance(const Instance&);
22
23    private:
24        Instance* _inst;
25        mutex _mtx;
26};

double check

两次判断的意义在于两方面:

  1. 效率: 避免并发时单次判断需要重复对互斥锁的加解锁操作
  2. 安全: 获取单例对象的并发安全性

sync

sync需要保证sync之后作用域的代码不会因为编译器的优化导致执行顺序的改变。

如果构造单例对象时使用_inst = new Instance;会产生并发安全问题,其内部的调用顺序为:

  1. 开辟内存空间
  2. 在内存位置执行构造函数
  3. 将内存位置赋值给_inst

其中,2和3的执行顺序是可以被改变的,当3先与2执行时,会产生_Inst!=nullptr且并未调用构造函数的现象。

饿汉模式

 1
 2Instance* Instance::_inst = new Instance;
 3
 4class Instance {
 5    public:
 6        static Instance* GetInstance() {
 7            return _inst;
 8        }
 9
10    private:
11        Instance();
12        Instance(const Instance&);
13
14    private:
15        static Instance* _inst;
16        mutex _mtx;
17};
Latest Posts