16. January 2022
单例模式
单例模式
程序中只存在一个单独的对象,单例模式的写法分为两种:
- 懒汉模式: 在使用的时候才创建。
- 饿汉模式: 在程序启动时就创建。
懒汉模式
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
两次判断的意义在于两方面:
- 效率: 避免并发时单次判断需要重复对互斥锁的加解锁操作
- 安全: 获取单例对象的并发安全性
sync
sync需要保证sync之后作用域的代码不会因为编译器的优化导致执行顺序的改变。
如果构造单例对象时使用_inst = new Instance;
会产生并发安全问题,其内部的调用顺序为:
- 开辟内存空间
- 在内存位置执行构造函数
- 将内存位置赋值给_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};