单例模式的典型优缺点评价:饿汉,懒汉与多线程安全
单例模式的应用案例:缓存
应用
在读取Config的时候,可能需要一些参数进行获取值,比如
Data:www.xxx.com
Option:1
host:http://
其中,data与option是固定的,如果每次取出config.ini里面的内容都需要new一个AppConfig对象,此时内存消耗会变大、所以单例模式中就可以定义一个全局且唯一的一个对象进行读取config
单例模式特点
1 构造函数是私有的
2 有一个全局静态的类属性
3 只允许在类的内部进行构造这个类
4 不依赖new实例化调用类的getInstance方法进行类内部构造
5 线程安全问题
单例模式线程安全问题
懒汉模式
Static Void * getInstance()
{
If(m_singleton == NULL)
m_singleton = mew this;
Return m_singleton;
}
当两条线程同时执行到m_singleton == NULL下面这行代码,由于另外一条线程的推进,使得m_singleton = mew this,而另外一条线程也会跟着m_singleton = mew this进行实例化类,就会出现两个对象,所以在异步当中时间片段被打乱就很容易出现多线程时造成内存泄露问题!
#include <iostream>
#include <sstream>
#include "afxwin.h"
using namespace std;
CRITICAL_SECTION g_cs;
class SingletonMode {
private:
SingletonMode()
{
m_singleton = nullptr;
cout << "构造一个SingletonMode类" << endl;
}
public:
static SingletonMode* getInstance()
{ //不能在此存放进入许可区、否则出异常
if (m_singleton == nullptr)
{
::EnterCriticalSection(&g_cs);
if (m_singleton == nullptr)
{
m_singleton = new SingletonMode;
}
::LeaveCriticalSection(&g_cs);
}
return m_singleton;
}
private:
static SingletonMode* m_singleton;
};
SingletonMode* SingletonMode::m_singleton = nullptr; //懒汉模式,如果不为nullptr则为饿汉模式
UINT Func(LPVOID)
{
cout << hex << SingletonMode::getInstance() << endl;
return 0;
}
int main(void)
{
//auto p1 = SingletonMode::getInstance();
//auto p2 = SingletonMode::getInstance();
InitializeCriticalSection(&g_cs);
for (int i = 0; i < 50; i++)
{
AfxBeginThread(Func, nullptr);
}
DeleteCriticalSection(&g_cs);
system("pause");
return 0;
}
普通项目中使用MFC库
1 在配置属性,常规选项中MFC的使用,选择MFC在共享DLL中或者是静态库中使用MFC
2 引入 include<afxwin.h>
3 使用AfxBeginThread函数即可创建线程,例如上AfxBeginThread创建50条线程
修正线程安全问题
1 使用临界区进行修正
2 定义临界区
定义结构体CRITICAL_SECTION g_cs;
初始化许可区:::InitializeCriticalSection(&g_cs)
进入许可区:::EnterCriticalSection(&g_cs)
退出许可区:::LeaveCriticalSection(&g_cs)
删除许可区:::DeleteCriticalSection(&g_cs)
3 对getInstance进行加入临界区,从而保证在异步的过程中产生全局且唯一的类
懒汉与饿汉的区别
SingletonMode* SingletonMode::m_singleton = new SingletonMode;
饿汉模式
在单例模式中,存着一个保存当前这个类的指针的静态变量
如果这个静态变量,在初始化的时候就已经被实例化对象了、此时多线程安全也就随之解决了
SingletonMode* SingletonMode::m_singleton = nullptr;
懒汉模式
如果这个静态变量,在初始化的时候是NULL模式、懒汉模式也称为延迟加载、非常常见的策略、在一个非常庞大的类时,在程序没有一定的需求创建这个类时,可以使用懒汉模式进行延迟创建,有助于资源的合理使用(这个过程存在线程安全)
字符串输出方式(一些其他类的使用)
ostringstream类实现(ostringstream是C++的一个字符集操作模板类,定义在sstream头文件中。ostringstream类通常用于执行C风格的串流的输出操作,格式化字符串,避免申请大量的缓冲区,替代sprintf。推荐)。
string sout;
ostringstream s;
s << "p1=" << hex << p1 << ",p2=" << hex << p2;
sout = s.str();
cout << sout << endl;
使用CString方式,使用_T宏进行自动转换编码,输出的时候使用wcout与endl
CString s;
s.Format(_T("p1=%p,p2=%p"), p1, p2);
wcout << s.GetString() << endl;
类型易语言使用封装方式输出十六进制
CString dec2hex(int n)
{
CString s;
s.Format(_T("%08X"), n);
return s;
}
CString s;
s = "p1=" + dec2hex((int)p1) + ",p2=" + dec2hex((int)p2);
wcout << s.GetString() << endl;