饿汉式
//恶汉模式
class Single {
public:
static Single* getInstance();
private:
Single();
Single(const Single &s);
Single & operator=(const Single &s);
static Single *instance;
};
Single::Single() {
}
Single::Single(const Single &s) {
}
Single & Single::operator=(const Single &s) {
return *this;
}
Single* Single::instance = new Single();
Single* Single::getInstance() {
return instance;
}
懒汉式
/*需要注意的是在多线程环境下使用一般的懒汉单例模式时,如果多个线程同时进入判断对象是否为空的代码段时,若此时对象为空,
那么多个线程就可能同时创建多个实例了。为解决这个问题,我们对getInstance方法中的一段加锁,这样就能防止创建多个实例现
象的发生。代码如下,值得注意的是,在getInstance方法中我们需要两次判断对象是否为空,这两个判断分别在临街区外和临界区
内,前者是为了不至于每次调用getInstance方法都要加锁,减小了系统开销;另外当有一个线程进入临界区时,其它线程也通过了
对象为空的条件判断,导致最后创建了多个对象情况的发生,后者则是为了防止这种情况的发生,即所谓“双重锁定”。*/
class Singleton {
public:
static Singleton * getInstance() {
if (instance == NULL) {
Lock();
if (instance == NULL) {
instance = new Singleton();
}
Unlock();
}
}
// 实现一个内嵌垃圾回收类
class Clear {
Clear() {};
~Clear() {
if (instance != NULL)
delete instance;
}
};
private:
static Singleton * instance;
Singleton() {};
Singleton(const Singleton &s) {};
Singleton & operator=(const Singleton &s) {
return *this;
}
};
Singleton * Singleton::instance = NULL;
Singleton::Clear cls;// 定义一个静态成员变量,程序结束时,系统会自动调用它的析构函数从而释放单例对象
class Singleton2 {
public:
static Singleton2 getInstance() {
Lock();
static Singleton2 instance;
Unlock();
return &instance;
}
private:
Singleton2() {};
Singleton2(const Singleton2 &) {};
Singleton2 & operator=(const Singleton2 &) {
return *this;
}
};
懒汉与饿汉优缺点
懒汉:故名思义,不到万不得已就不会去实例化类,也就是说在第一次用到类实例的时候才会去实例化,所以上边的经典方法被
归为懒汉实现;
饿汉:饿了肯定要饥不择食。所以在单例类定义的时候就进行实例化。
特点与选择:
由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
在访问量较小时,采用懒汉实现。这是以时间换空间。