Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

单例模式 #6

Open
wangzitiansky opened this issue Sep 2, 2020 · 0 comments
Open

单例模式 #6

wangzitiansky opened this issue Sep 2, 2020 · 0 comments
Labels
设计模式 🔞 设计模式总结

Comments

@wangzitiansky
Copy link
Owner

wangzitiansky commented Sep 2, 2020

单例模式

原文地址(更好的阅读体验): 📖

动机

  • 一个特殊的类,保证在系统中只存在有一个实例。
  • 绕过常规的构造器,提供一种机制来保证一个类只有一个实例

定义

保证一个类只有一个实例,并提供一个该实例的全局访问点

代码实现

  • 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;
    }
}
@wangzitiansky wangzitiansky created this issue from a note in 设计模式 (设计模式) Sep 2, 2020
@wangzitiansky wangzitiansky added the 设计模式 🔞 设计模式总结 label Sep 18, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
设计模式 🔞 设计模式总结
Projects
设计模式
设计模式
Development

No branches or pull requests

1 participant