C++ 单例设计模式
来源:互联网 发布:网络集成版驱动精灵 编辑:程序博客网 时间:2024/06/05 11:23
有些类只需要有一个实例,比如软件开发过程中的日志功能,因为我们要频繁的写log,不可能每次都要重新new一个日志实例,然后用完再delete。当然在C++中可以用全局变量来代替,但全局变量有太多的不可预测性,特别是在多线程的开发中,所以对全局变量我们是能不用就不用。此时单例设计模式就派上用场了。先上代码,在分析为何这么写。
// Singleton.h#pragma once#include <windows.h>class CSingleton{public: static CSingleton* GetInstance(); bool WriteLog(const TCHAR* szLogPath, const TCHAR* szLogInfo);private: CSingleton(){}; // ~CSingleton(){}; CSingleton(const CSingleton&); CSingleton& operator=(const CSingleton&); static CSingleton* m_Instance; static HANDLE m_pSingleMutex; class CGarbo { public: ~CGarbo() { if (m_Instance != NULL) { WaitForSingleObject(m_pSingleMutex, INFINITE); if (m_Instance != NULL) { delete m_Instance; m_Instance = NULL; } ReleaseMutex(m_pSingleMutex); } if (m_pSingleMutex != NULL) { CloseHandle(m_pSingleMutex); m_pSingleMutex = NULL; } } }; static CGarbo m_Garbo;};
单例模式的定义: 保证一个类只有一个实例,并提供一个可供全局访问的访问点。
- m_Instance是类的唯一实例,把它申明成静态私有变量,通过公有函数GetInstance返回
- 类要创建实例需调用类的构造函数,为了防止类外部创建类的实例,把类的构造函数申明私有
- CGarbo 用来进行资源释放
程序运行结束时,系统会自动调用静态成员m_Garbo的析构函数,该析构函数进行资源释放,这种资源的释放是在程序员不知道的情况下进行的;
—— 程序运行结束时,系统会自动析构所有的全局变量,我们知道全局变量和静态变量都储存在静态存储区,所以在析构时,也会析构静态成员变量
// Singleton.cpp#include "stdafx.h"#include "Singleton.h"#include <fstream>using namespace std;CSingleton* CSingleton::m_Instance = NULL;CSingleton::CGarbo CSingleton::m_Garbo;HANDLE CSingleton::m_pSingleMutex = CreateMutex(NULL, FALSE, NULL);CSingleton* CSingleton::GetInstance(){ if (m_Instance == NULL) { WaitForSingleObject(m_pSingleMutex, INFINITE); if (m_Instance == NULL) { m_Instance = new CSingleton(); } ReleaseMutex(m_pSingleMutex); } return m_Instance;}bool CSingleton::WriteLog(const TCHAR* szLogPath, const TCHAR* szLogInfo){ FILE * pLogFile; int nRtn = -1; _tfopen_s(&pLogFile, szLogPath, _T("a")); if (pLogFile == NULL) { return false; } nRtn = _ftprintf(pLogFile, _T("%s\n"), szLogInfo); if (nRtn < 0) { fflush(pLogFile); fclose(pLogFile); return false; } fflush(pLogFile); fclose(pLogFile); return true;}
GetInstance()代码分析:
// 普通单例实例化,线程不安全// 如果多个线程同时调用GetInstance(),假设其中A线程执行完1后且此时m_Instance=NULL,该线程挂起,// 然后当B线程调用GetInstance()时,m_Instance=NULL仍为空,B线程会创建CSingleton的一个实例// 某个时刻当A线程继续执行时,由于之前1语句已经执行完,故A线程也会创建CSingleton的一个实例,这和单例模式的初衷是不符合的CSingleton* CSingleton::GetInstance(){ if (m_Instance == NULL)/*1*/ { m_Instance = new CSingleton();/*2*/ } return m_Instance;}// 为了线程安全问题,在创建实例的时候加锁,创建完后释放// 当有多个线程调用GetInstance()时,每次都要加锁解锁,频繁的锁操作对性能是有影响的// 并且当多个线程同时调用GetInstance()时,只有一个线程能够继续执行,其他线程要先等待,同样对性能也有影响CSingleton* CSingleton::GetInstance(){ WaitForSingleObject(m_pSingleMutex, INFINITE);/*Lock*/ if (m_Instance == NULL) { m_Instance = new CSingleton(); } ReleaseMutex(m_pSingleMutex);/*UnLock*/ return m_Instance;}// 为了解决上述问题,引入了“双锁检”机制(1 And 3)// 当有多个线程调用GetInstance()时,如果m_Instance为NULL,GetInstance()直接返回,既不用频繁的锁操作,线程也不用等待// 那为什么要有3了? 原因和普通单例线程不安全的原因相同CSingleton* CSingleton::GetInstance(){ if (m_Instance == NULL)/*1*/ { WaitForSingleObject(m_pSingleMutex, INFINITE);/*2*/ if (m_Instance == NULL)/*3*/ { m_Instance = new CSingleton(); } ReleaseMutex(m_pSingleMutex); } return m_Instance;}
Last
// main 函数中调用CSingleton *singleObj = CSingleton::GetInstance();singleObj->WriteLog(_T("D:\\Single.log"), _T("info000000"));
阅读全文
0 0
- (C#)设计模式 之 单例模式
- 设计模式--单例模式 C++实现
- 设计模式之单例模式(C++)
- 设计模式(C++) -----单例模式
- 【设计模式C++】单例模式
- 单例设计模式(C#) 简单模式
- 单例设计模式(C#) 懒汉模式
- C#--设计模式之单例模式
- 单例模式的设计(C++)
- Objective-C 设计模式之单例
- Objective-c中的单例设计模式
- 设计模式,objective-c单例
- Objective-c ;单例设计模式
- Objective-c 单例设计模式
- objective c单例设计模式
- Objective-c 单例设计模式
- Objective-C之单例设计模式
- Objective-c 实现单例设计模式
- CSS布局整理
- Python正则表达式操作指南
- MySQL简单查询语句
- 图片弹出预览js
- 支付倒计时与圆环波纹动画效果
- C++ 单例设计模式
- Oracle查询基础练习
- Go开发工具
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- 从《战狼2》中看PPT哲学
- MySQL插入数据
- 弗洛伊德最短路径算法
- rest hateoas spring
- Activity生命周期