单例模式(Singleton)
:保证一个类仅有一个实例,并提供一个访问它的全局访问点。
通常我们可以让一个全局变量使得一个对象访问,但它不能防止你实例化多个对象。 一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,并且它可以提供一个访问该实例的方法。
构造方法让其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;
}