首页 > 其他 > 详细

[设计模式] 设计模式课程(十一)-- 单例模式

时间:2020-06-01 16:13:31      阅读:43      评论:0      收藏:0      [点我收藏+]
  • 属于“对象性能”模式
  • 面向对象很好地解决了“抽象”的问题,但不可避免地要付出一定的代价。对于通常情况来讲,面向对象的成本大都可忽略不计(继承),但某些特殊情况,面向对象带来的成本须谨慎处理(虚函数倍乘效应)
  • 动机:软件系统中有些特殊的类,必须确保它们在系统中只存在一个实例,才能确保逻辑正确及良好的效率
  • 确保一个类仅有一个实例,并提供一个该实例的全局访问点
  • 如何绕过常规构造器,提供一种机制,保证类只有一个实例
  • 类设计者的责任,而不是使用者的责任
  • 拷贝构造函数设计成私有(c++中,缺省构造函数和缺省拷贝构造函数都是共有的)
  • 高并发场景下,锁的代价过大
  • 双检查锁(锁前锁后都检查,防止两个进程前后脚进来),但内存读写reorder不安全,会导致双检查锁失效(线程在指令层次抢时间片,可能与代码顺序不一致)
  • new的默认顺序:分配内存--调用构造器--地址赋值给变量;实际优化后的可能顺序:分配内存--地址赋值给变量--调用构造器(导致线程B拿到了内存地址,而并没有执行构造器)
  • 解决:new过程不能reoder。Java:加volatile声明;C++atomic,memory_order_relaxed/release
  • Singleton模式中的实例构造器可设置为protected以允许子类派生
  • Singleton一般不支持拷贝构造函数和Clone接口,因为有可能导致多个对象实例,与模式初衷违背
  • 双锁检查正确实现,确保多线程环境下安全的Singleton
技术分享图片
 1 class Singleton{
 2 private:
 3     Singleton();
 4     Singleton(const Singleton& other);
 5 public:
 6     static Singleton* getInstance();
 7     static Singleton* m_instance;
 8 };
 9 
10 Singleton* Singleton::m_instance=nullptr;
11 
12 //线程非安全版本
13 Singleton* Singleton::getInstance() {
14     if (m_instance == nullptr) {
15         m_instance = new Singleton();
16     }
17     return m_instance;
18 }
19 
20 //线程安全版本,但锁的代价过高
21 Singleton* Singleton::getInstance() {
22     Lock lock;
23     if (m_instance == nullptr) {
24         m_instance = new Singleton();
25     }
26     return m_instance;
27 }
28 
29 //双检查锁,但由于内存读写reorder不安全
30 Singleton* Singleton::getInstance() {
31     
32     if(m_instance==nullptr){
33         Lock lock;
34         if (m_instance == nullptr) {
35             m_instance = new Singleton();
36         }
37     }
38     return m_instance;
39 }
40 
41 //C++ 11版本之后的跨平台实现 (volatile)
42 std::atomic<Singleton*> Singleton::m_instance;
43 std::mutex Singleton::m_mutex;
44 
45 Singleton* Singleton::getInstance() {
46     Singleton* tmp = m_instance.load(std::memory_order_relaxed);
47     std::atomic_thread_fence(std::memory_order_acquire);//获取内存fence
48     if (tmp == nullptr) {
49         std::lock_guard<std::mutex> lock(m_mutex);
50         tmp = m_instance.load(std::memory_order_relaxed);
51         if (tmp == nullptr) {
52             tmp = new Singleton;
53             std::atomic_thread_fence(std::memory_order_release);//释放内存fence
54             m_instance.store(tmp, std::memory_order_relaxed);
55         }
56     }
57     return tmp;
58 }
View Code

 

[设计模式] 设计模式课程(十一)-- 单例模式

原文:https://www.cnblogs.com/cxc1357/p/12310649.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!