“保证一个类仅有一个实例,并提供一个访问它的全局访问点“
1.类图:
2.懒汉式
代码:
#include <iostream> using namespace std; // 懒汉式 class Singleton { public: static Singleton *getInstance() { if (_instance == NULL) { _instance = new Singleton(); } return _instance; } static void releaseInstance() { if (_instance != NULL) { delete _instance; _instance = NULL; } } private: Singleton(){ } ~Singleton(){ } //防止外部多次delete同一块内存 Singleton(const Singleton &other) { } // 禁止拷贝构造 Singleton &operator=(const Singleton& other) { } //禁止外部使用=操作符重载,改变已有对象 static Singleton *_instance; }; Singleton *Singleton::_instance = NULL;
3.饿汉式
代码:
#include <iostream> using namespace std; class Singleton { public: static Singleton *getInstance() { return _instance; //直接返回静态实例 } static void releaseInstance() { if (_instance != NULL) { delete _instance; _instance = NULL; } } private: Singleton(){ cout << "Singleton called" << endl; } ~Singleton(){ } //防止外部多次delete同一块内存 Singleton(const Singleton &other) { } // 禁止拷贝构造 Singleton &operator=(const Singleton& other) { } //禁止外部使用=操作符重载,改变已有对象 static Singleton *_instance; }; Singleton *Singleton::_instance = new Singleton(); void test() { Singleton *s1 = Singleton::getInstance(); Singleton *s2 = Singleton::getInstance(); cout << s1 << endl; cout << s2 << endl; Singleton::releaseInstance(); Singleton::releaseInstance(); }
4.懒汉式遇上多线程,需要同步
bug代码:
#include <iostream> #include <Windows.h> #include <process.h> using namespace std; class Singleton { private:
//构造函数不是线程安全函数 Singleton() { cout << "构造Singleton begin" << endl; Sleep(1000); //用来模拟多线程中对象的初始化可能耗时较长的情景 cout << "构造Singleton end" << endl; count++; //对象数加1 } public: static Singleton *getInstance() { if (_instance == NULL) { _instance = new Singleton; } return _instance; } static void releaseInstance() { if (_instance != NULL) { delete _instance; _instance = NULL; } } static int getCount() { return count; } private: static Singleton *_instance; static int count; ~Singleton(){ } Singleton(const Singleton& other){} Singleton &operator=(const Singleton& other) {} }; Singleton *Singleton::_instance = NULL; int Singleton::count = 0; //用来统计对象的个数 void threadFunc(void *) { Singleton::getInstance(); } void test() { HANDLE hThread[3]; for (int i = 0; i < 3; ++i) { hThread[i] = (HANDLE)_beginthread(threadFunc, 0, NULL); //创建线程 构造单例 } for (int i = 0; i < 3; ++i) { WaitForSingleObject(hThread[i], INFINITE); // 等待线程退出 } cout << "count: " << Singleton::getCount() << endl; } int main() { test(); cin.get(); return 0; }
效果:
在上面代码的基础上修改,加入同步机制:
加入:
#include <afxmt.h> //需要右击项目,选择属性=>c/c++>预处理器>预处理定义添加_AFXDLL static CCriticalSection cs; // 定义全局临界区
去掉:
#include <Windows.h>
修改getInstance()方法:
static Singleton *getInstance() { if (_instance == NULL) // 只有在_instance等于NULL的时候才开始时候加锁机制, 并进行二次检查 { cs.Lock(); if (_instance == NULL) { _instance = new Singleton; } cs.Unlock(); } return _instance; }
效果: