单例模式
设计模式
单例模式
保证一个类只有一个实例,并提供一个访问它的全局访问点。
根据对象初始化的位置不同,单例模式有懒汉式和饿汉式两种。
懒汉式
调用getInstance时才构造对象。
优点:用不到就不新建对象,节省了空间;
缺点:每次getInstance时都需要进行判断。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| class Singleton_l { private: Singleton_l() { cout << "构造函数运行" << endl; }; ~Singleton_l();
public: static Singleton_l* getInstance() { if(m_instance == NULL) { m_instance = new Singleton_l; } return m_instance; }
static void freeInstance() { if(m_instance != NULL) { delete m_instance; m_instance = NULL; } }
private: static Singleton_l* m_instance; };
Singleton_l* Singleton_l::m_instance = NULL;
|
饿汉式
程序开始就新建了对象。
优点:不需要每次都判断;
缺点:提前占用了空间。且由于需要提前申请,有些时候不能使用饿汉式。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| class Singleton_e { private: Singleton_e() { cout << "构造函数运行" << endl; }; ~Singleton_e();
public: static Singleton_e* getInstance() { return m_instance; }
static void freeInstance() { if(m_instance != NULL) { delete m_instance; m_instance = NULL; } }
private: static Singleton_e* m_instance; };
Singleton_e* Singleton_e::m_instance = new Singleton_e();
|
总:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include <iostream>
using namespace std;
class Singleton_l { private: Singleton_l() { cout << "构造函数运行" << endl; }; ~Singleton_l();
public: static Singleton_l* getInstance() { if(m_instance == NULL) { m_instance = new Singleton_l; } return m_instance; }
static void freeInstance() { if(m_instance != NULL) { delete m_instance; m_instance = NULL; } }
private: static Singleton_l* m_instance; };
class Singleton_e { private: Singleton_e() { cout << "构造函数运行" << endl; }; ~Singleton_e();
public: static Singleton_e* getInstance() { return m_instance; }
static void freeInstance() { if(m_instance != NULL) { delete m_instance; m_instance = NULL; } }
private: static Singleton_e* m_instance; };
Singleton_l* Singleton_l::m_instance = NULL; Singleton_e* Singleton_e::m_instance = new Singleton_e(); int main() { Singleton_l* p1 = Singleton_l::getInstance(); Singleton_l* p2 = Singleton_l::getInstance(); if(p1 == p2){ cout << "一个实例" << endl; } cout << "Hello world!" << endl; return 0; }
|
多线程时的单例模式
多线程时单例模式的问题
出现在懒汉式单例模式中。如果多个线程都调用getInstance函数,可能出现多个线程都构造了新的对象,这就不是单例模式了。也就是说,构造函数不是线程安全函数。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
| #include <iostream> #include <windows.h>
using namespace std;
class Singleton_l { private: Singleton_l() { cout << "构造函数运行begin" << endl; Sleep(1000); cout << "构造函数运行end" << endl; }; ~Singleton_l();
public: static Singleton_l* getInstance() { if(m_instance == NULL) { cnt++; m_instance = new Singleton_l; } return m_instance; }
static void freeInstance() { if(m_instance != NULL) { delete m_instance; m_instance = NULL; cnt--; } }
void prints() { cout << "instance print test" << endl; }
int getCnt() { return cnt; }
private: static Singleton_l* m_instance; static int cnt; };
Singleton_l* Singleton_l::m_instance = NULL; int Singleton_l::cnt = 0;
void MyThreadFunc (void*) { cout << "newthread" << endl; Singleton_l::getInstance()->prints(); } int main() { HANDLE hThread[10]; for (int i = 0; i < 3; i++) hThread[i] = (HANDLE)_beginthread(MyThreadFunc, 0, NULL); for (int i = 0; i < 3; i++) WaitForSingleObject(hThread[i],INFINITE); cout << "Hello world!" << endl; cout << Singleton_l::getInstance()->getCnt() << endl; return 0; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 输出: newthreadnewthread 构造函数运行begin
构造函数运行begin newthread 构造函数运行begin 构造函数运行end 构造函数运行end instance print test 构造函数运行endinstance print test
instance print test Hello world! 3
|
解决方法
- 双重锁定:进行两次检查,不用让线程每次都加锁
- 加锁操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
| #include <iostream> #include <windows.h> #include <mutex>
using namespace std;
mutex mut;
class Singleton_l { private: Singleton_l() { cout << "构造函数运行begin" << endl; Sleep(1000); cout << "构造函数运行end" << endl; }; ~Singleton_l();
public: static Singleton_l* getInstance() { if(m_instance == NULL) { mut.lock(); if(m_instance == NULL) { cnt++; m_instance = new Singleton_l; } mut.unlock (); } return m_instance; }
static void freeInstance() { if(m_instance != NULL) { delete m_instance; m_instance = NULL; cnt--; } }
void prints() { cout << "instance print test" << endl; }
int getCnt() { return cnt; }
private: static Singleton_l* m_instance; static int cnt; };
Singleton_l* Singleton_l::m_instance = NULL; int Singleton_l::cnt = 0;
void MyThreadFunc (void*) { cout << "newthread" << endl; Singleton_l::getInstance()->prints(); } int main() { HANDLE hThread[10]; for (int i = 0; i < 3; i++) hThread[i] = (HANDLE)_beginthread(MyThreadFunc, 0, NULL);
for (int i = 0; i < 3; i++) WaitForSingleObject(hThread[i],INFINITE); cout << "Hello world!" << endl; cout << Singleton_l::getInstance()->getCnt() << endl; return 0; }
|
1 2 3 4 5 6 7 8 9 10 11
| 输出: newthreadnewthread
newthread 构造函数运行begin 构造函数运行end instance print test instance print test instance print test Hello world! 1
|