单例模式(Singleton):
保证一个类仅有一个实例,并提供一个访问它的全局访问点。
MFC编程中有且只有一个工具箱,只能启动一个任务管理器(win7),一个国家只有一个领导人等情景下应用。
怎么实现呢?
构造函数私有化,只有自己能调用构造函数;给外部提供一个获得指针的静态方法;提供全局访问点。
代码:
// SingletonPattern.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<iostream>
#include<thread>
#include<windows.h>
using namespace std;
//临界区
class RAII_CrtcSec
{
private:
CRITICAL_SECTION crtc_sec;
public:
RAII_CrtcSec() { ::InitializeCriticalSection(&crtc_sec); }
~RAII_CrtcSec() { ::DeleteCriticalSection(&crtc_sec); }
RAII_CrtcSec(const RAII_CrtcSec &) = delete;
RAII_CrtcSec & operator=(const RAII_CrtcSec &) = delete;
//给数据上锁 防止多个线程同时访问
void Lock() { ::EnterCriticalSection(&crtc_sec); }
//去锁
void Unlock() { ::LeaveCriticalSection(&crtc_sec); }
};
RAII_CrtcSec RC;
class Single
{
private:
Single()
{
cout << "我被创建了!" << endl;
}
static Single *s;
public:
static Single *GetInstance()
{
//不考虑多线程
/*if (s == NULL)
{
s = new Single();
}*/
//考虑多线程
//效率低 无论是否创建过 都要枷锁
/*RC.Lock();
if (s == NULL)
{
s = new Single();
}
RC.Unlock();*/
//效率更高
if (s == NULL) //如果没有被创建过 加锁 如果创建过 就不加锁
{
RC.Lock();
if (s == NULL)
{
s = new Single();
}
RC.Unlock();
}
return s;
}
void aaa()
{
cout << "我的地址:";
}
};
Single* Single::s = NULL;
void creat()
{
Single *s = Single::GetInstance();
s->aaa();
cout << s << endl;
}
int main()
{
/*Single * t = Single::GetInstance();
Single *tt = Single::GetInstance();
cout << "指向同一地址:" << t << " " << tt << endl;*/
//只能创建一次且地址相同,此时单例模式完成,但是对于多线程还是不行,测试如下:
thread t1(creat);
t1.detach();
thread t2(creat);
t2.detach();
Sleep(1000);
//发现被创建两次,且地址不同
//使用临界区 互斥访问 结果 只实例化一次 且 地址相同 使用两次if判断效率更高
return 0;
}
上面代码用到了c++11多线程、处理临界区变量的相关知识,还有不断优化的过程,注释很详细吗,就不多说了。
懒汉和饿汉:
懒汉:顾名思义,很懒,不到关键时刻不做事,也就是说第一次要用到这个类时才实例化。正是由于这一点,当多线程同时“第一次”访问这个类时,很容易出现问题,所以懒汉模式要考虑到线程安全的问题。
饿汉:就是特别饿,见到就要吃,吃的已经准备好了,也就是说这个类在程序一开始就实例化完成,放在那。
上面的代码很明显时懒汉模式,虽然早早地声明了,但是实例化是在GetInstance()方法中,第一次用到这个方法才实例化,。
那饿汉模式的代码又怎么写呢?