声明:VS2012中已经支持C++11了,因此下面的程序在VS2012中可以运行。如果版本比2012低,可能因为不支持:std::mutex,std::shared_ptr而失败。
#ifndef SINGLETON_H #define SINGLETON_H #include <memory> #include <mutex> using namespace std; /* 关键: 1 双重检查机制: //先判断如果第一次创建,然后枷锁,然后在判断是否为空,实例化;如果一进入就加锁,那么效率不好; //如果判断完了再进入加锁,那么多个进程仍然会多次实例化, if(0 == _instance.get()) { //锁定互斥量,在构造时锁定互斥量,析构时自动解锁,保证互斥量的正确操作 std::unique_lock<std::mutex> uLock(_mutex); if(0 == _instance.get()) 2 //防止实例化失败,C++中对指针赋值操作并不能保证原子操作,如果有某个线程1执行到这里, //赋值到一半,线程1挂起,线程2开始执行,这是_instance出于任何任何 std::shared_ptr<T> temp(new T); _instance = temp; 3 友元类的使用:可以访问,Singleton类中声明friend class A;那么Singlton中的私有成员和变量可以被A类访问 #define DECLARE_SINGLETON_CLASS(type) \ friend class shared_ptr< type > ; \ friend class Singleton< type > ; */ /*线程安全的单例模式,防止多个线程同时执行_instance.reset(new T);同时产生两个新的对象, 然后马上释放一个,这跟Singleton模式本意不符合*/ template<typename T> class Singleton { private: Singleton(void){} Singleton(const Singleton& ){} ~Singleton(void){} Singleton& operator = (const Singleton& ){} public: //static T* instance(); static T* instance() { //先判断如果第一次创建,然后枷锁,然后在判断是否为空,实例化;如果一进入就加锁,那么效率不好; //如果判断完了再进入加锁,那么多个进程仍然会多次实例化, if(0 == _instance.get()) { //锁定互斥量,在构造时锁定互斥量,析构时自动解锁,保证互斥量的正确操作 std::unique_lock<std::mutex> uLock(_mutex); if(0 == _instance.get()) { //防止实例化失败,C++中对指针赋值操作并不能保证原子操作,如果有某个线程1执行到这里, //赋值到一半,线程1挂起,线程2开始执行,这是_instance出于任何任何 std::shared_ptr<T> temp(new T); _instance = temp; } } return _instance.get(); } private: static std::shared_ptr<T> _instance;//静态成员函数,指向该类的指针;注意这里定义的实际上是一个类型T的指针 static std::mutex _mutex; //独占对象 }; template<typename T> shared_ptr<T> Singleton<T>::_instance; template<typename T> mutex Singleton<T>::_mutex; /*声明单例模式类的类型,使:指针和单例类成为友元类*/ #define DECLARE_SINGLETON_CLASS(type) \ friend class shared_ptr< type > ; \ friend class Singleton< type > ; #endif
下面是一个使用示例:Service.h文件
#ifndef SERVICEMANGER_H #define SERVICEMANGER_H #include "singleton.h" #include <iostream> class ServiceManger { DECLARE_SINGLETON_CLASS(ServiceManger); public: void Run() { std::cout << "我是张飞,搞单例模式两个晚上" << std::endl; } //注意,不能声明为私有,否则报错 ServiceManger(void); ~ServiceManger(void); }; typedef Singleton<ServiceManger> SSManger; #endif
Service.cpp
#include "ServiceManger.h" ServiceManger::ServiceManger(void) { } ServiceManger::~ServiceManger(void) { }
main.cpp文件
#include <iostream> #include "ServiceManger.h" using namespace std; int main(int argc,char* argv[]) { SSManger::instance()->Run(); getchar(); return 0; }