单例模式:懒汉模式、恶汉模式
懒汉:第一次用到类实例的时候才会去实例化。(考虑线程安全性)
饿汉:单例类定义的时候就进行实例化。
适用场景
懒汉:在访问量较小时,采用懒汉实现。这是以时间换空间。
饿汉:由于要进行线程同步,所以在访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。
一、懒汉模式
#pragma once
#include <iostream>
#include <mutex>
#include <thread>
//初始化静态成员变量
SingleInstance* SingleInstance::m_SingleInstance = NULL;
std::mutex SingleInstance::m_Mutex;
/// 加锁的懒汉式实现 //
class SingleInstance
{
public:
// 获取单实例对象
static SingleInstance*& GetInstance()
{
// 这里使用了两个 if判断语句的技术称为双检锁;好处是,只有判断指针为空的时候才加锁,
// 避免每次调用 GetInstance的方法都加锁,锁的开销毕竟还是有点大的。
if (m_SingleInstance == NULL)
{
//std::unique_lock<std::mutex> lock(m_Mutex); // 加锁
m_Mutex.lock();
if (m_SingleInstance == NULL)
{
m_SingleInstance = new (std::nothrow) SingleInstance;
}
m_Mutex.unlock();
}
return m_SingleInstance;
}
//释放单实例,进程退出时调用
static void deleteInstance()
{
m_Mutex.lock();
if (m_SingleInstance)
{
delete m_SingleInstance;
m_SingleInstance = NULL;
}
m_Mutex.unlock();
}
// 打印实例地址
void Print()
{
std::cout << "我的实例内存地址是:" << this << std::endl;
}
private:
// 将其构造和析构成为私有的, 禁止外部构造和析构
SingleInstance()
{
std::cout << "构造函数" << std::endl;
}
~SingleInstance()
{
std::cout << "析构函数" << std::endl;
}
// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
SingleInstance(const SingleInstance& signal);
const SingleInstance& operator=(const SingleInstance& signal);
private:
// 唯一单实例对象指针
static SingleInstance* m_SingleInstance;
static std::mutex m_Mutex;
};
二、饿汉模式
#pragma once
#include <iostream>
#include <thread>
//初始化静态成员变量
SingleInstance* SingleInstance::m_SingleInstance = new (std::nothrow) SingleInstance;//启动程序时直接实现
/// 饿汉式实现 //
class SingleInstance
{
public:
// 获取单实例对象
static SingleInstance*& GetInstance()
{
return m_SingleInstance;
}
//释放单实例,进程退出时调用
static void deleteInstance()
{
if (m_SingleInstance)
{
delete m_SingleInstance;
m_SingleInstance = NULL;
}
}
// 打印实例地址
void Print()
{
std::cout << "我的实例内存地址是:" << this << std::endl;
}
private:
// 将其构造和析构成为私有的, 禁止外部构造和析构
SingleInstance()
{
std::cout << "构造函数" << std::endl;
}
~SingleInstance()
{
std::cout << "析构函数" << std::endl;
}
// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值
SingleInstance(const SingleInstance& signal);
const SingleInstance& operator=(const SingleInstance& signal);
private:
// 唯一单实例对象指针
static SingleInstance* m_SingleInstance;
};
#include <thread>
#include <iostream>
#include<windows.h>
#include "SingleInstance.h"
#define NUM_THREADS 5 // 线程个数
// 线程函数
void PrintHello(int threadid)
{
std::cout << "Hi, 我是线程 ID:[" << threadid << "]" << std::endl;
// 打印实例地址
SingleInstance::GetInstance()->Print();
}
int main(void)
{
int indexes[NUM_THREADS] = { 0 }; // 用数组来保存i的值
int ret = 0;
int i = 0;
std::cout << "main() : 开始 ... " << std::endl;
for (i = 0; i < NUM_THREADS; i++)
{
std::cout << "main() : 创建线程:[" << i << "]" << std::endl;
indexes[i] = i; //先保存i的值
std::thread thr(PrintHello, indexes[i]);
thr.detach();
}
// 手动释放单实例的资源
Sleep(10000);
SingleInstance::deleteInstance();
std::cout << "main() : 结束! " << std::endl;
return 0;
}