-
Notifications
You must be signed in to change notification settings - Fork 1
Open
Labels
设计模式 🔞设计模式总结设计模式总结
Description
单例模式
原文地址(更好的阅读体验): 📖
动机
- 一个特殊的类,保证在系统中只存在有一个实例。
- 绕过常规的构造器,提供一种机制来保证一个类只有一个实例
定义
保证一个类只有一个实例,并提供一个该实例的全局访问点
代码实现
- Cpp
类的定义
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;
}双检查锁,由于内存读写指令重排序不安全
在 m_instance = new Singleton()中,指令流分为三部分
1.分配内存
2.调用构造器,将内存初始化
3.将内存地址赋值给 m_instance
但是在 CPU 级别,可能有指令重排序,可能顺序为
1.分配内存
2.将内存地址赋值给 m_instance
3.调用构造器,初始化内存
在重排序的顺序中,如果 TreadA 执行到了 m_instance = new Singleton()的第二步骤
此时 m_instance 不为 nullptr
如果此时有另一个线程执行了 if(m_instance==nullptr) 此判断,则认为m_instance可以使用,其实不能使用
Singleton* Singleton::getInstance() {
if(m_instance==nullptr){
Lock lock;
if (m_instance == nullptr) {
m_instance = new Singleton();
}
}
return m_instance;
}- Java
public final class Singleton {
// The field must be declared volatile so that double check lock would work
// correctly.
// 必须使用 volatile 关键字修饰来避免指令重排序
private static volatile Singleton instance;
public String value;
private Singleton(String value) {
this.value = value;
}
public static Singleton getInstance(String value) {
if(instance == null){
synchronized(Singleton.class) {
if (instance == null) {
instance = new Singleton(value);
}
}
}
return instance;
}
}Metadata
Metadata
Assignees
Labels
设计模式 🔞设计模式总结设计模式总结