文章目录

  • 多线程时的单例
  • 双重锁定
  • 饿汉式单例
  • 懒汉式单例
  • 使用内部类析构
  • 使用智能指针实现



单例模式(Singleton):保证一个类仅有一个实例,并提供一个访问它的全局访问点。

  通常我们可以让一个全局变量使得一个对象访问,但它不能防止你实例化多个对象。 一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。


android 单例模式销毁 单例模式安全_android 单例模式销毁

构造方法让其private,堵死了外界利用new创建此类的实例的可能。

多线程时的单例

static Config * Config::instance()
{
    //加锁(多线程场景下)
    m_mutex.acquire();
    if (NULL == m_instance)
    {
        m_instance = new Config();
        m_instance->init();
    }
    //解锁
    m_mutex.release();
    return m_instance;
}

双重锁定

static Config * instance()
    {
        if (NULL == m_instance)
        {
            //加锁(多线程场景下)
            m_mutex.acquire();
            if (NULL == m_instance)
            {
                Config * pInstance = new Config();
                pInstance->init();
                m_instance = pInstance;
            }
            //解锁
            m_mutex.release();
        }
        return m_instance;
    }

饿汉式单例

  • 饿汉式单例:即静态初始化的方式,是类一加载就实例化对象。所以要提前占用系统资源。就是不管你要不要都会直接创建一个对象。只能有一个static对象(线程安全)。
class Singleton
{
public:
	static Singleton* getInstance ()
	{
		return &_instance;
	}
private:
	static Singleton _instance;
	Singleton() {};
	Singleton(const Singleton&) = delete;
	Singleton& operator=(const Singleton&) = delete;
};
Singleton Singleton::_instance;

懒汉式单例

  • 懒汉式单例:需要考虑多线程访问的安全性问题。
  • 没有公有构造方法,一个公有静态工厂方法,和一个静态实例变量构造函数私有

使用内部类析构

//一个较全的懒汉式单例模式
#include <iostream>
#include <pthread.h>
#include <mutex>
using namespace std;
class Singleton
{
public:
    static Singleton *getInstance()
    {
        if (instance == nullptr)
        {
            pthread_mutex_lock(& _mutex); //再进行 次判空有多个线程在第一次判
            //断空时进入了第一个if语句,此时如果不在进行判空在解锁后会有线程再次去进行new对象
            if (instance == nullptr)
                instance = new Singleton();
            pthread_mutex_unlock(& _mutex);
        }
        return instance;
    }
private:
    Singleton()
    {
        cout << "Singleton()" << endl;
    }

    Singleton(const Singleton &instance)
    {
        cout <<"singleton (const Singleton&)" <<endl;
    }

    ~Singleton() {
        pthread_mutex_destroy(&_mutex);
        cout << "~Singleton()" << endl;
    }
    class Release   //自动析构instance类
    {


    public:
        ~Release()      //使用一个内部类,对instance进行delete
        {
            if(instance != nullptr)
            {
                delete instance ;
                instance = nullptr;
            }
        }
    };
    static Release rel;
    static Singleton *instance;
    static pthread_mutex_t _mutex;
};

Singleton *Singleton::instance = nullptr;
pthread_mutex_t Singleton::_mutex = PTHREAD_MUTEX_INITIALIZER;
Singleton::Release Singleton::rel;

int main() {
    Singleton *p1 = Singleton::getInstance();
    Singleton *p2 = Singleton::getInstance();
    Singleton *P3 = p2;
    cout << p1 <<" "<< p2 << endl;
    if (p1 == p2)
        cout << "两个对象是相同的实例" << endl;
    return 0;
}

输出

Singleton()
0x1041770 0x1041770
两个对象是相同的实例
~Singleton()

使用智能指针实现

问题:shared_ptr无法访问私有化的析构函数

#include <iostream>
#include <process.h>
#include <pthread.h>
#include <mutex>
#include <windows.h>
#include <memory>
using namespace std;
class Singleton
{
public:
    static std::shared_ptr<Singleton> getInstance()
    {
        if (instance == nullptr)
        {
            pthread_mutex_lock(& _mutex); //再进行 次判空有多个线程在第一次判
            //断空时进入了第一个if语句,此时如果不在进行判空在解锁后会有线程再次去进行new对象
            if (instance == nullptr)
                instance.reset(new Singleton(),Singleton::DestroyInstance);
            pthread_mutex_unlock(& _mutex);
        }
        return instance;
    }
    static void print(){
            cout<<m_count<<endl;
    }
    
private:
    Singleton()
    {
        cout << "Singleton()" << endl;
        Sleep(1000);
        m_count ++;// 加sleep为了放大效果
    }
    ~Singleton() {
        pthread_mutex_destroy(&_mutex);
        cout << "~Singleton()" << endl;
    }
    Singleton(const Singleton &instance)
    {
        cout <<"singleton (const Singleton&)" <<endl;
    }
    static void DestroyInstance(Singleton *instance) //自定义一个释放实例的函数
    {
        delete instance; // 释放单例对象
    }


    static int m_count;
    static std::shared_ptr<Singleton> instance;
    static pthread_mutex_t _mutex;
};

// 回调函数
void threadFunc(void *p){
    DWORD id = GetCurrentThreadId();        // 获得线程id
    cout<<id<<endl;
    Singleton::getInstance()->print();     // 构造函数并获得实例,调用静态成员函数
}

std::shared_ptr<Singleton> Singleton::instance = nullptr;
pthread_mutex_t Singleton::_mutex = PTHREAD_MUTEX_INITIALIZER;
int Singleton::m_count = 0;

int main() {
    int threadNum = 3;
    HANDLE threadHdl[100];

    // 创建3个线程
    for(int i = 0; i<threadNum; i++){
        threadHdl[i] = (HANDLE)_beginthread(threadFunc, 0, nullptr);
    }

    // 让主进程等待所有的线程结束后再退出
    for(int i = 0; i<threadNum; i++){
        WaitForSingleObject(threadHdl[i], INFINITE);
    }

    return 0;
}