什么是单例模式
单例模式是一种经典的,常用的。常考的设计模式。
设计模式:大佬们针对一些经典的常见场景,给定一些对应的解决方案
什么是饿汉?什么是懒汉?
概念不太好理解,我举个例子大家应该就能明白了
这里是个洗碗的例子。
第一种:吃完饭立刻洗碗因为下顿饭好了的时候可以立即吃到饭,这是饿汉方式:时刻准备着
第二种:吃完饭把碗放下,等吃下顿饭的时候再去洗碗,这是懒汉方式:用的时候再准备
有没有发现二者的区别呢?没错,懒汉模式的核心思想是“延时加载”,从而能够优化服务器的启动速度。
这与我们之前在线程讲过的写实拷贝有异曲同工之妙,因为写实拷贝也提高了创建子进程的速度。
饿汉方式实现单例模式
template<typename T>
class Singleton{
static T data; //提前准备好数据
public:
static T* GetInstance()
{
return &data;
}
};
通过上面Singleton这个被包装好的类,我们在一个进程中只能有一个T对象的实例。
懒汉方式实现单例模式
template<typename T>
class Singleton{
static T* inst;
public:
static T* GetInstance()
{
if(inst==NULL)
{
inst=new T(); //用的时候才new一个对象
}
return inst;
}
};
但是这里存在一个严重的问题:线程不安全!!
因为在第一次调用的时候,如果被两个线程同时调用则可能会创建出两份T对象的实例,不符合单例模式的要求。但是后续调用不会有问题。
这里我做出修改如下:
线程安全版:懒汉模式
template<typename T>
class Singleton{
volatile static T* inst; //防止被编译器优化
static std::mutex lock;
public:
static T* GetInstance()
{
if(inst==NULL) //双重判断降低锁冲突的概率,提高性能
{
lock.lock();
if(inst==NULL)
inst=new T(); //用的时候才new一个对象
lock.unlock();
}
return inst;
}
};
注意事项:
- 加锁解锁的位置
- 双重if 判断,可以减少锁的消耗,避免不必要的锁竞争
- volatile 关键字保持内存可见性,防止编译器过度优化
Linux的内容,基本到这里就告一段落了,其他内容我在前面的博客也讲到了,有需要的小伙伴可以在我的专栏里查看。。
下篇博客博主准备总结网络相关知识了,不要忘记关注博主哦~