您的位置:首页 > 其它

单例模式的懒汉模式和饿汉模式

2017-07-30 12:30 274 查看
单例模式:
要求:
1、单例类只有唯一一个实例对象
2、单例类提供唯一获取这一实例接口GetInstance()
重点:解决线程安全问题

设计难点:
一、饿汉模式(编译加载阶段完成初始化实例):
只需设计一个GetInstance()方法,并直接初始化唯一实例对象(可在方法外初始化也可在方法内初始化)。
二、懒汉模式(在运行时初始化实例):
1、在运行时第一次调用该实例时再初始化。
2、考虑线程安全问题:即初始化时在new前加lock_guard类型的锁,保证new一系列操作的原子性,该锁必须定义为static,保证所有线程用一把锁。RAII 该锁出作用域自动释放。
3、考虑内存优化问题:内存优化可能打乱new的几个步骤的顺序,使用内存栅栏MemoryBarrier()解决该问题。
4、定义一个内部类,在作用域结束前调用该类对象,从而调用该对象的析构,释放单例对象,保证内存不泄露的问题。
共同设计难点:
1、必须将构造、拷贝构造、operator=写在private限定符内,后两个只声明不实现。
2、必须将唯一实例对象和GetInstance方法定义为static的。

懒汉模式和饿汉模式对比:
懒汉模式:
1、在运行代码时才初始化实例,需要解决线程安全问题。
2、加载速度快,运行获取对象慢
3、写法复杂,但所有场景均使用
饿汉模式:
1、在编译加载时初始化实例,不会产生线程安全问题。
2、加载速度慢,运行获取对象速度快
3、写法简单,但适用性受限(如动态库)

代码实现:

#pragma once
#include<cassert>
#include<mutex>
#include&
4000
lt;windows.h>
using namespace std;
//懒汉模式 --- 在运行时创建单例对象
namespace LAZY
{
class singleton
{
public:
static singleton* GetInstance()
{
if (_init == NULL)   //只有第一次创建对象时走一次
{
//加锁,保证new和赋值为原子的  RAII----出作用域释放锁
lock_guard<mutex> lock(_mut);

//new的步骤:
//1.operator new开空间
//2.调构造函数
//3.赋值
//_init = new singleton;

//由于内存优化可能将2、3优化顺序颠倒-----采用内存栅栏防止优化
singleton* tmp = new singleton;
MemoryBarrier();  //内存栅栏---保证栅栏之前的必定比栅栏之后的先运行
_init = tmp;
}
return _init;
}
void print()
{
cout << "singleton:" << _a << endl;
}

//内部类,完成单例对象的释放工作
struct GC
{
~GC()
{
DelInstance();
}
};
static void DelInstance()
{
lock_guard<mutex> lock(_mut);
if (_init != NULL)
{
cout << "delete" << endl;
delete _init;
_init = NULL;
}
}
private:
singleton()
:_a(0)
{}
~singleton()
{
//释放数据库等操作
}
//只声明不实现
singleton(const singleton&);
singleton& operator=(const singleton&);

int _a;
//定义静态成员和锁
static singleton* _init;
static mutex _mut;   //静态锁保证全局是一把锁---保证new和赋值的原子性
};
singleton* singleton::_init = NULL;
mutex singleton::_mut;

void Test()
{
singleton::GetInstance()->print();
singleton::GetInstance()->print();
singleton::GetInstance()->print();
getchar();
}
//创建gc对象,出作用域时释放_init
static singleton::GC gc;
}

//饿汉模式  --- 编译加载时初始化唯一实例对象
namespace HUNGRY
{
class singleton
{
public:
//获取单例对象必须是静态方法
static singleton& GetInstance()
{
//assert(_init);
//return *_init;

static singleton _init;
return _init;
}

void print()
{
cout << "singleton:" << _a << endl;
}
private:
singleton()
:_a(0)
{}
//将拷贝构造operator=设置为防拷贝
singleton(const singleton&);
singleton& operator=(const singleton&);

int _a;  //单例类成员变量

//static singleton* _init;
};
//初始化单例对象
//singleton* singleton::_init = new singleton;

void Test()
{
singleton::GetInstance().print();
singleton::GetInstance().print();
singleton::GetInstance().print();
getchar();
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: