单例模式

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;

 

 

posted @ 2022-11-29 21:17  我就不告诉你我是谁  阅读(21)  评论(0编辑  收藏  举报