Skip to content

单例模式 #6

@wangzitiansky

Description

@wangzitiansky

单例模式

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

动机

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

定义

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

代码实现

  • 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

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions