一、基础的单例模式实现
- 构造函数声明为 private 或 protect ,防止被外部函数实例化;
- 内部保存一个 private static 的类指针保存唯一的实例;
- 实例的动作由一个 public 的类方法如 getInstance( ) 完成,该方法也返回单例类唯一的实例。
- 具体实现
class singleton
{
protected:
singleton(){}
private:
static singleton* p;
public:
static singleton* getInstance();
};
singleton* singleton::p = NULL;
singleton* singleton::getInstance()
{
if (p == NULL)
p = new singleton();
return p;
}
看起来一切都很优雅,但是!该方法是线程不安全的,如果有两个线程同时首次调用getInstance()方法且同时检测到p是NULL值,则两个线程会同时构造一个实例给p,显然这是错误的。
二、懒汉模式与饿汉模式
1. 单例的两类实现方法
- 懒汉:在第一次用到类实例的时候才会去实例化,故上边的经典方法被归为懒汉实现;
- 饿汉:在单例类定义的时候就进行实例化。
2. 特点与选择:
- 以空间换时间:由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现。
- 以时间换空间:在访问量较小时,采用懒汉实现。
3. 饿汉模式实现:
class singleton
{
protected:
singleton(){}
private:
static singleton* p;
public:
static singleton* getInstance();
};
singleton* singleton::p = new singleton; //单例类定义的时候就进行实例化
singleton* singleton::getInstance()
{
return p;
}
4. 线程安全的懒汉模式实现
- 加锁
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } private: static singleton* p; public: static pthread_mutex_t mutex; static singleton* getInstance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::p = NULL; singleton* singleton::getInstance() { if (p == NULL) { pthread_mutex_lock(&mutex); if (p == NULL) p = new singleton(); pthread_mutex_unlock(&mutex); } return p; }
- 内部静态变量
class singleton { protected: singleton() { pthread_mutex_init(&mutex); } public: static pthread_mutex_t mutex; static singleton* getInstance(); }; pthread_mutex_t singleton::mutex; singleton* singleton::getInstance() { pthread_mutex_lock(&mutex); static singleton obj; pthread_mutex_unlock(&mutex); return &obj; }
此方法在 getInstance 函数里定义一个静态的实例,也可以保证拥有唯一实例,在返回时只需要返回其指针。