设计模式
- 设计模式:是一套被反复使用、多数人知晓的、经过分类的、代码设计经验的总结。
- 使用设计模式的目的:为了代码的可重用性,让代码更容易被他人理解,保证代码的可靠性。设计模式使代码编写真正工程化。
单例模式
某服务器程序中,配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中其他对象通过这个单例对象获取配置信息,简化了复杂环境下的配置管理。
- 单例模式:一个类只能创建一个对象
- 该模式码可以保证系统中该类只有一个实例,并提供一个访问他的全局访问点,该实例被所有程序模块共享。
(1)饿汉模式
- 简言之,饿汉模式就是程序启动时就创建一个唯一的实例对象,不管将来用不用
- 优点:简单
- 缺点:可能导致进程启动慢,并且若有多个单例类对象实例启动,则顺序不确定
- 若这个单例对象在多线程高并发环境下频繁使用,性能要求较高,使用饿汉模式可以避免资源竞争,提高响应速度
class Hun_Singleton
{
public:
static Hun_Singleton * getInstance()
{
return &m_instance;
}
private:
Hun_Singleton(){}
Hun_Singleton(Hun_Singleton const& hun_singleton){}
Hun_Singleton& operator=(Hun_Singleton const& hun_singleton){}
static Hun_Singleton m_instance;
};
Hun_Singleton Hun_Singleton::m_instance;
int main()
{
return 0;
}
(2)懒汉模式
- 简言之,懒汉模式就是延迟加载
- 优点:第一次使用实例对象时,创建对象;进程启动无负载;多个单例实例启动顺序自由控制
- 缺点:复杂
- 如果单例对象构造十分耗时或占用很多资源,如加载插件、初始化网络连接、读取文件等,而有可能该对象程序运行时不会用到,那么也要在程序一开始就进行初始化,就会导致程序启动时非常缓慢。这种情况使用懒汉模式更好
#include<iostream>
#include<mutex>
#include<thread>
using namespace std;
class Laz_Singleton
{
public:
static Laz_Singleton * getInstance()
{
//Double-Check方式加锁,保证效率和线程安全
if(nullptr == m_pInstance)
{
m_mtx.lock();
if(nullptr == m_pInstance)
{
m_pInstance = new Laz_Singleton();
}
m_mtx.unlock();
}
return m_pInstance;
}
//内嵌垃圾回收类
class CGarbo
{
public:
~CGarbo()
{
if(Laz_Singleton::m_pInstance)
{
delete Laz_Singleton::m_pInstance;
}
}
};
//定义一个静态成员变量,程序结束时,系统会自动调用析构函数释放单例对象
static CGarbo cgarbo;
private:
Laz_Singleton(){}
Laz_Singleton(Laz_Singleton const& laz_singleton){}
Laz_Singleton& operator=(Laz_Singleton const& laz_singleton){}
static Laz_Singleton * m_pInstance;//单例对象指针
static mutex m_mtx;//互斥锁
};
Laz_Singleton * Laz_Singleton::m_pInstance = nullptr;
Laz_Singleton::CGarbo cgarbo;
mutex Laz_Singleton::m_mtx;
void func(int n)
{
cout<<Laz_Singleton::getInstance()<<endl;
}
//多线程下加锁与不加锁的区别
int main()
{
thread t1(func, 10);
thread t2(func, 10);
t1.join();
t2.join();
cout<<Laz_Singleton::getInstance()<<endl;
cout<<Laz_Singleton::getInstance()<<endl;
return 0;
}
编译命令
g++-4.8 -std=c++11 laz_singleton.cpp -lpthread