设计模式的理解:单例模式(singleton) -凯发k8官方网
单例模式使用的目的是 ①一个类只能初始化出一个对象 ②保证对象是线程安全的。
其做法:
1、将 构造函数 和拷贝构造函数 设置为私有 并将自身类的指针设置成静态成员,其函数方法也设置成静态方法。保证该类只创建一个对象
2、通过加锁的方式,对 对象访问加以限制
class singleton { private:static singleton * instance; singleton (){} singleton(const singleton& other);public:static singleton* getinstance() { if (instance == nullptr) { instance = new singleton(); } return instance; } }以上在单线程中是可以满足一个类对象只会被初始化一次的条件。但是在多线程中 假如其中一个线程在执行 instance = new singleton(); 语句前,而另外一个刚好进入 if 语句时,这个类就会被初始化两次。所以上述的编码方式时线程不安全的。
二、双重加锁
class singleton { private:static singleton * instance; singleton (){} singleton(const singleton& other);public:static singleton* getinstance() { if (instance == nullptr) { lock lock;if(instance == nullptr){instance = new singleton(); }} return instance; } }上述代码是双重锁机制,当一个线程先获取到锁的时候,第二个线程读锁时就会等待第一个锁初始化完对象后才继续执行。但是上述写法没有考虑到内存读写reorder不安全。
正常创建对象实例会走三步骤
1) 分配对象内存
2) 调用构造器,执行初始化
3) 将对象的引用赋值给变量。
然而在编译器优化等问题下,在实际可能的运行顺序是,先执行第三步再执行第二部,即先引用给对象再调用构造器。
如果
假如其中一个线程在执行 instance = new singleton(); 语句时,分配完了内存,将对象将对象的引用赋值给变量,此时第二个线程判断 if (instance == nullptr) 不成立直接返回了一个还未初始化完的对象。那么就会造成线程不安全。这个创建对象的二三步骤乱序执行实际上叫重排序。
在java ,c#中 ,新增了一个关键字volatile,在声明成员变量时 volatile static singleton instance; 表示禁止 instance创建对象时重排序。
而在c 11版本的跨平台实现
//c 11版本之后的跨平台实现 // atomic c 11中提供的原子操作 std::atomic
或者有更简洁的c 写法,但在c 11版本前不支持。
class singleton{ public:// 注意返回的是引用。static singleton& getinstance(){static singleton m_instance; //局部静态变量return m_instance;} private:singleton(); //私有构造函数,不允许使用者自己生成对象singleton(const singleton& other); };
总结
以上是凯发k8官方网为你收集整理的设计模式的理解:单例模式(singleton)的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: 设计模式的理解:构造器模式(builde
- 下一篇: 设计模式的理解:享元模式 (flywei