单例模式
1.单例模式简介
(1)多线程模式下,共享同一个资源或者操作同一个资源,单例模式保证一个类只生成唯一的一个对象
例如:多个线程使用同一个socket资源;配置文件的读取时。
(2)实现单例步骤常用步骤:
a) 构造函数私有化 b) 提供一个全局的静态方法(全局访问点)
c) 在类中定义一个静态指针,指向本类的变量的静态变量指针
2. 饿汉式单例(多线程下没问题)
不管用不用,main函数之前就已经把这个实例给创建出来了
#include <iostream>
using namespace std;
class Singelton
{
private:
Singelton() //第1步:构造函数的私有化
{
m_singer = NULL;
m_count = 0;
cout << "构造函数 Singelton ... do" << endl;
}
public:
static Singelton *getInstance() //第2步:提供一个全局的静态方法(全局访问点)
{
return m_singer;
}
static void FreeInstance()
{
if (m_singer != NULL)
{
delete m_singer;
m_singer = NULL;
m_count = 0;
}
}
private:
static Singelton *m_singer; //第3步:在类中定义一个静态指针,指向本类的变量的静态变量指针
static int m_count;
};
Singelton *Singelton::m_singer = new Singelton; //饿汉式单例的关键点:不管你创建不创建实例,均把实例new出来
int Singelton::m_count = 0;
int main()
{
cout << "演示 饿汉式" << endl;
Singelton *p1 = Singelton::getInstance();
Singelton *p2 = Singelton::getInstance();
if (p1 != p2)
{
cout << "不是同一个对象" << endl;
}
else
{
cout << "是同一个对象" << endl; //结果是同一个对象
}
Singelton::FreeInstance();
Singelton::FreeInstance();
}
3. 懒汉式单例(多线程下需进行同步,本案例采用Double-Checked Locking 优化)
(1)使用的时候,才会去创建对象(2)多线程中会导致多个实例的产生,从而导致运行代码不正确以及内存的泄露。
原因: C++中构造函数并不是线程安全的,C++中的构造函数简单来说分两步:
第一步:内存分配
第二步:初始化成员变量
由于多线程的关系,可能当我们在分配内存好了以后,还没来得急初始化成员变量,就进行线程切换。
另外一个线程拿到所有权后,由于内存已经分配了,但是变量初始化还没进行,因此打印成员变量的相关值会发生不一致现象。
1 #include <iostream>
2 #include <QMutex>
3 using namespace std;
4
5 //互斥锁
6 static QMutex mutex;
7 class Singleton
8 {
9 private:
10 Singleton() //第1步:构造函数私有化
11 {
12 m_singer = NULL;
13 m_count = 0;
14 cout << "构造函数 Singelton ... do" << endl;
15 }
16 //防止拷贝构造和赋值操作
17 Singleton(const Singleton &){;};
18 Singleton& operator = (const Singleton &){;};
19 public:
20 static Singleton *getInstance() //第2步:提供一个全局的静态方法(全局访问点)
21 {
22 if(m_singer == NULL) //double check
23 {
24 mutex.Lock();
25 //二次检查很重要,防止重复创建,比如第1个线程和第2线程都在mutex.Lock()等着;
26 //第一个线程创建完了,第二个线程再往下走时不判断为空就会重复创建了.
27 if(m_singer == NULL)
28 {
29 m_singer = new Singleton();
30 }
31 mutex.Unlock();
32 }
33 return m_singer;
34 }
35 private:
36 static Singleton *m_singer; //第3步:在类中定义一个静态指针,指向本类的变量的静态变量指针
37 static int m_count;
38 };
39
40 Singleton *Singleton::m_singer = NULL; //懒汉式 并没有创建单例对象
41 int Singleton::m_count = 0;