1. 定义
保证一个类仅有一个实例,并提供一个该实例的全局访问点。
2. 适用场景
- 在软件系统中,经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例,才能确保它们的逻辑正确性、以及良好的效率。
- 如何绕过常规的构造器,提供一种机制来保证一个类只有一个实例?
- 这应该是类设计者的责任,而不是使用者的责任。
3. 要点总结
- Singleton模式中的实例构造器可以设置为protected 以允许子类派生。
- Singleton模式一般不要支持拷贝构造函数和Clone接口, 因为这有可能导致多个对象实例,与Singleton模式的初衷违背。
- 如何实现多线程环境下安全的Singleton ?注意对双检查锁的正确实现。
4. Demo
class Singleton{
private:
Singleton();
Singleton(const Singleton& other);
public:
static Singleton* getInstance();
static Singleton* m_instance;
};
Singleton* Singleton::m_instance=nullptr;
//线程非安全版本
Singleton* Singleton::getInstance() {
if (m_instance == nullptr) {
m_instance = new Singleton();
}
return m_instance;
}
//线程安全版本,但锁的代价过高
Singleton* Singleton::getInstance() {
Lock lock;
if (m_instance == nullptr) {
m_instance = new Singleton();
}
return m_instance;
}
//双检查锁,但由于内存读写reorder不安全(不能用)
Singleton* Singleton::getInstance() {
if(m_instance==nullptr){
Lock lock;
if (m_instance == nullptr) {
//此处很有可能reorder导致异常
//此处有三个步骤:1.分配内存;2调用构造器;3.将构造器做完了的指针(分配的内存地址)返回值赋给m_instance ,正常执行顺序为:1->2->3
//但是在CPU层面,指令级别这3步可能reorder可能执行顺序为1->3->2
//这样当一个进程进来执行至3时,另一个进程进发现m_instance !=nullptr,就直接返回了m_instance ,但是这个时候m_instance 是没有被构造,是不能用的。
m_instance = new Singleton();
}
}
return m_instance;
}
//C++ 11版本之后的跨平台实现 (volatile)
std::atomic<Singleton*> Singleton::m_instance;
std::mutex Singleton::m_mutex;
Singleton* Singleton::getInstance() {
Singleton* tmp = m_instance.load(std::memory_order_relaxed);
std::atomic_thread_fence(std::memory_order_acquire);//获取内存fence
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(m_mutex);
tmp = m_instance.load(std::memory_order_relaxed);
if (tmp == nullptr) {
tmp = new Singleton;
std::atomic_thread_fence(std::memory_order_release);//释放内存fence
m_instance.store(tmp, std::memory_order_relaxed);
}
}
return tmp;
}
本专栏文章:
- 01-C++面向对象设计原则
- 02-C++模式概述
- 03-模板方法(Template Method)
- 04-策略模式(Strategy)
- 05-观察者模式(Observer)
- 06-装饰模式(Decorator)
- 07-桥模式(Bridge)
- 08-工厂方法(Factory Method)
- 09-抽象工厂(Abstract Factory)
- 10-原型模式(Prototype)
- 11-构建器(Builder)
- 12-单件模式(Singleton)
- 13-享元模式(Flyweight)
- 14-门面模式(Façade)
- 15-代理模式(Proxy)
- 16-适配器(Adapter)
- 17-中介者(Mediator)
- 18-状态模式(State)
- 19-备忘录(Memento)
- 20-组合模式(Composite)
- 21-迭代器(Iterator)
- 22-职责链(Chain of Resposibility)
- 23-命令模式(Command)
- 24-访问器(Visitor)
- 25-解析器(Interpreter)
- 26-C++设计模式总结