单例模式,就说保证一个类仅有一个实例,并提供一个访问它的全局访问点。
单例模式结构图
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;
}
应用场景
优点:
- 保证唯一的实例;
- 可以严格控制客户怎样访问实例以及何时访问,即对唯一实例的受控访问。
网友评论