单例模式C++

单例模式,就说保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式结构图

image

单例模式基本代码

class Singleton {
private:
    static Singleton* instance;
    Singleton() {} // 将构造函数设为私有,禁止外界调用
public:
    static Singleton* GetInstance() {  // 获取实例的唯一全局访问点
        if (instance == NULL) {
            instance  = new Singleton();
        } 
        return instance;
    }
};

懒汉式和饿汉式

  • 饿汉式单例类:类被加载时就将自己实例化,称之为饿汉式实例类。因为类一加载就实例化对象,会提前占用系统资源,但不会有多线程的安全性问题。
  • 懒汉式单例类:在第一次被引用时才将自己实例化,称之为懒汉式实例类。但其面临多线程安全性问题,需要双重锁定才可以保证安全。

懒汉式

#include <iostream>
using namespace std;

template<class T>
class Singleton{
private:
    static T* instance;
    Singleton() {}
public:
    static T* GetInstance() {
        return instance;
    }
};

template<class T>
T* Singleton<T>::instance = new T(2);   // 类刚加载时就初始化

int main() {
    int* p1 = Singleton<int>::GetInstance();
    cout << *p1 << endl;   // 2

    int* p2 = Singleton<int>::GetInstance();
    cout << *p2 << endl;   // 2

    return 0;
}

饿汉式

在多线程环境中,如果多个线程同时访问Singleton类,调用GetInstane()方法,会导致创建多个实例。这样可以通过加锁解决:

#include <iostream>
#include "pthread.h"
using namespace std;

template<class T>
class Singleton{
private:
    static T* instance;
    Singleton() {}
    static pthread_mutex_t mutex;
public:
    static T* GetInstance() {
        pthread_mutex_lock(&mutex);
        if (instance == NULL) {
            instance = new T(3);
        }
        pthread_mutex_unlock(&mutex);
        return instance;
    }
};

template<class T>
pthread_mutex_t Singleton<T>::mutex = PTHREAD_MUTEX_INITIALIZER;

template<class T>
T* Singleton<T>::instance = NULL;

int main() {
    int* p1 = Singleton<int>::GetInstance();
    cout << *p1 << endl;     // 3

    int* p2 = Singleton<int>::GetInstance();
    cout << *p2 << endl;     // 3

    return 0;
}
双重锁定

以上方法每次调用GetInstance方法都需要调用pthread_mutex_lock(&mutex),这样会影响性能。可以通过双重锁定来解决:

#include <iostream>
#include "pthread.h"
using namespace std;

template<class T>
class Singleton{
private:
    static T* instance;
    Singleton() {}
    static pthread_mutex_t mutex;
public:
    static T* GetInstance() {
        if (instance == NULL) {
            pthread_mutex_lock(&mutex);
            if (instance == NULL) {
                instance = new T(3);
            }
            pthread_mutex_unlock(&mutex);
        }
        return instance;
    }
};

template<class T>
pthread_mutex_t Singleton<T>::mutex = PTHREAD_MUTEX_INITIALIZER;

template<class T>
T* Singleton<T>::instance = NULL;

int main() {
    int* p1 = Singleton<int>::GetInstance();
    cout << *p1 << endl;     // 3

    int* p2 = Singleton<int>::GetInstance();
    cout << *p2 << endl;     // 3

    return 0;
}

应用场景

优点:

  1. 保证唯一的实例;
  2. 可以严格控制客户怎样访问实例以及何时访问,即对唯一实例的受控访问。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容