好久不写博客,最近都在复习,心血来潮,写一篇关于设计模式--单例模式的博客。。。。
我们知道,对于C++OOP思想,我们怎么可以说不熟悉设计模式,接下来就简单地介绍一下单例模式。
在我们的设计当中经常要保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。思考一下,什么时候构造函数不能手动调用?答:自然是将构造函数私有化;再思考,构造函数私有化了,我们如何将我们的对象构造呢?答:提供一个公有的接口;再思考,我们如何保证实例化一次呢?答:把成员变量(唯一的对象)定义为静态变量,根据静态变量的特点,一旦被赋值之后将不能再被赋值。所以我们初步的单例模式就出来了;如下:
版本一:
class Singleton
{
public:
Singleton *Getobject()
{
if(object==NULL) //懒加载,只有使用的时候才会生效
{
project=new Singleton();
}
return project;
private:
Singleton(){};
static Singleton *project;
}
版本二:
当我们考虑到线程安全的时候,我们的初步版本就不在适用了,试想一下,当我们一个线程判断了if语句成立,所以要进去构造object的时候,另一个线程此时刚好构造完了object,那我们岂不是构造object两次,所以考虑到线程安全问题,我们需要保证if语句里面是临界区,保证原子操作,所以我们加上互斥锁来保证
class Singleton
{
public:
Singleton *Getobject()
{
pthread_mutex_lock(&mutex);
if(project==NULL) //懒加载,只有使用的时候才会生效
{
project=new Singleton();
}
pthread_mutex_unlock(&mutex);
return project;
private:
Singleton(){};
static Singleton *project;
}
版本三:我们知道锁是很重的,假如我们是单线程和多线程共存,那我们每次都要加锁解锁岂不是很麻烦,所以我们在这里加一层判断,就是为了提高单线程访问时的效率
class Singleton
{
public:
Singleton *Getobject()
{
if(project==NULL)
{
pthread_mutex_lock(&mutex);
if(project==NULL) //懒加载,只有使用的时候才会生效
{
project=new Singleton();
}
pthread_mutex_unlock(&mutex);
}
return project;
}private:
Singleton(){};
static Singleton *project;
}
版本四:考虑编译器的指令优化和CPU的动态指令优化
volatile关键字阻止编译器为了提高速度将一个变量缓存到寄存器内而不写回内存
volatile关键字阻止编译器调整操作volatile变量的指令操作
barrier指令会阻止CPU对指令进行动态换序优化
class Singleton
{
public:
volatile static Singleton* getIntance()
{
if (project== NULL)//懒加载,只有在使用时才生成
{
pthread_mutex_lock(&mutex);//多线程线程安全问题
if (project== NULL)//单线程时的效率问题
{
Singleton* temp = new Singleton;
barrier();//防止CPU对指令进行动态换序优,使对象的构造一定在barrier完成,因 //此赋值给pobject的对象是完好的
project= temp;
}
pthread_mutex_lock(&mutex);
}
return project;
}
private:
Singleton(){}
volatile static Singleton *project;
};