c++单例模式的介绍与实现

1.单例模式

  单例模式是基本的设计模式之一,它属于创建型模式,提供一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。

  在程序设计上须保证一个类仅有一个实例,并提供一个访问它的全局访问点,该实例被所有程序模块共享。

  在进行单例类封装的时候,避免被调用方构造,构造函数需私有化。

2. 饿汉单例模式

  程序启动时就实例化了该对象,并没有推迟到第一次使用该对象时再进行实例化。

  在这样的情况下,多线程调用单例和它的方法,只会进行实例的使用而不会进行实例的创建。

  为什么说它是线程安全的呢?

  因为C++11保证静态局部变量的初始化过程是线程安全的,一个线程在初始化 m 的时候,其他线程执行到 m 的初始化这一行的时候,就会挂起。

  代码实现如下:

class Singleton{
    
    
public:
    static Singleton* m_instance_ptr;
    static Singleton* get_instance() {
    
    
        return m_instance_ptr;
    }
private:
    Singleton() {
    
     }
};

Singleton* Singleton::m_instance_ptr = new Singleton();

int main(){
    
    
    Singleton* instance1 = Singleton::get_instance();
    Singleton* instance2 = Singleton::get_instance();
    return 0;
}

  一句话总结:因为类实例化就会占用内存,所以浪费资源,但由于提前初始化了实例,所以效率较高,且不存在线程安全问题。

  由于程序流程是程序员控制的,所以在饿汉模式下,只要能保证前期能创建实例,就不存在那些抢占多实例的问题。

  如果在程序运行过程中没有使用到实例对象,那么在饿汉模式下该实例对象就被浪费掉了,这个场景可能需要使用懒汉单例模式。

3. 懒汉单例模式

  懒汉单例模式会在第一次使用它的时候才进行对象的实例化。

  代码实现如下:

class Singleton {
    
    
public:
    static Singleton* m_instance_ptr;
    static Singleton* get_instance() {
    
    
        if(m_instance_ptr == NULL)
            m_instance_ptr = new Singleton();
        return m_instance_ptr;
    }
private:
    Singleton() {
    
     }
};

Singleton* Singleton::m_instance_ptr = NULL;

int main(){
    
    
    Singleton* instance1 = Singleton::get_instance();
    Singleton* instance2 = Singleton::get_instance();
    return 0;
}

  如果多线程竞争创建实例时,需要考虑加锁。

  代码实现如下:

class Singleton {
    
    
public:
    static Singleton* m_instance_ptr;
    static std::mutex m_mutex;
    static Singleton* get_instance() {
    
    
        // double-check来保证不会每次进来都去获取锁,来提高性能,先判断不为空的话,直接返回了数据
        if(m_instance_ptr == NULL) {
    
    
            m_mutex.lock();
            if(m_instance_ptr == NULL)
                m_instance_ptr = new Singleton();
            m_mutex.unlock();
        }
        return m_instance_ptr;
    }
private:
    Singleton() {
    
     }
};

Singleton* Singleton::m_instance_ptr = NULL;
std::mutex Singleton::m_mutex;

void thread_instance_do() {
    
    
    Singleton* instance = Singleton::get_instance();
    while(1) {
    
    
        // do something
    }
}

int main(){
    
    
    std::thread thread1(thread_instance_do);
    std::thread thread2(thread_instance_do);
    thread1.join();
    thread2.join();
    return 0;
}

  一句话总结:由于延迟加载,所以节省资源,导致效率低,且存在线程安全问题。


  参考文章

猜你喜欢

转载自blog.csdn.net/initiallht/article/details/125647225