怎么建立企业网站平台,做公众号的网站有哪些,前端开发语言有哪几种,阿里云 wordpress访问很慢定义
保证一个类仅有一个实例#xff0c;并提供一个该实例的全局访问点。
应用场景
在软件系统中#xff0c;经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例#xff0c;才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器#xff0c;提供一种…定义
保证一个类仅有一个实例并提供一个该实例的全局访问点。
应用场景
在软件系统中经常有这样一些特殊的类,必须保证它们在系统中只存在一个实例才能确保它们的逻辑正确性、以及良好的效率。如何绕过常规的构造器提供一种机制来保证一个类只有一个实例?这应该是类设计者的责任,而不是使用者的责任。
结构 代码示例
普通懒汉式线程不安全
多线程情况下线程不安全
//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H/// 普通懒汉式实现 -- 线程不安全 //
#include iostream // std::cout
#include mutex // std::mutex
#include pthread.h // pthread_create
class SingleInstance
{public:// 获取单例对象static SingleInstance *GetInstance();// 释放单例进程退出时调用static void deleteInstance();// 打印单例地址void Print();private:// 将其构造和析构成为私有的, 禁止外部构造和析构SingleInstance();~SingleInstance();// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值SingleInstance(const SingleInstance signal);const SingleInstance operator(const SingleInstance signal);private:// 唯一单例对象指针static SingleInstance *m_SingleInstance;
};//初始化静态成员变量
SingleInstance *SingleInstance::m_SingleInstance NULL;SingleInstance* SingleInstance::GetInstance()
{if (m_SingleInstance NULL){m_SingleInstance new (std::nothrow) SingleInstance; // 没有加锁是线程不安全的当线程并发时会创建多个实例}return m_SingleInstance;
}void SingleInstance::deleteInstance()
{if (m_SingleInstance){delete m_SingleInstance;m_SingleInstance NULL;}
}void SingleInstance::Print()
{std::cout 我的实例内存地址是: this std::endl;
}SingleInstance::SingleInstance()
{std::cout 构造函数 std::endl;
}SingleInstance::~SingleInstance()
{std::cout 析构函数 std::endl;
}
/// 普通懒汉式实现 -- 线程不安全 //// 线程函数
void *PrintHello(void *threadid)
{// 主线程与子线程分离两者相互不干涉子线程结束同时子线程的资源自动回收pthread_detach(pthread_self());// 对传入的参数进行强制类型转换由无类型指针变为整形数指针然后再读取int tid *((int *)threadid);std::cout Hi, 我是线程 ID:[ tid ] std::endl;// 打印实例地址SingleInstance::GetInstance()-Print();pthread_exit(NULL);
}#endif//test.cpp
/****************************************************/
#include Singleton.h
#include pthread.h // pthread_create
#define NUM_THREADS 5 // 线程个数
int main()
{pthread_t threads[NUM_THREADS] {0};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的值// 传入的时候必须强制转换为void* 类型即无类型指针ret pthread_create(threads[i], NULL, PrintHello, (void *)(indexes[i]));if (ret){std::cout Error:无法创建线程, ret std::endl;exit(-1);}}// 手动释放单实例的资源SingleInstance::deleteInstance();std::cout main() : 结束! std::endl;return 0;
}加锁懒汉式线程安全
//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H
#include pthread.h // pthread_create
#include iostream // std::cout
#include mutex // std::mutex
/// 加锁的懒汉式实现 //
class SingleInstance
{public:// 获取单实例对象static SingleInstance *GetInstance();//释放单实例进程退出时调用static void deleteInstance();// 打印实例地址void Print();private:// 将其构造和析构成为私有的, 禁止外部构造和析构SingleInstance();~SingleInstance();// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值SingleInstance(const SingleInstance signal);const SingleInstance operator(const SingleInstance signal);private:// 唯一单实例对象指针static SingleInstance *m_SingleInstance;static std::mutex m_Mutex;
};//初始化静态成员变量
SingleInstance *SingleInstance::m_SingleInstance NULL;
std::mutex SingleInstance::m_Mutex;SingleInstance *SingleInstance::GetInstance()
{// 这里使用了两个 if判断语句的技术称为双检锁好处是只有判断指针为空的时候才加锁// 避免每次调用 GetInstance的方法都加锁锁的开销毕竟还是有点大的。if (m_SingleInstance NULL) {std::unique_lockstd::mutex lock(m_Mutex); // 加锁if (m_SingleInstance NULL){m_SingleInstance new (std::nothrow) SingleInstance;}}return m_SingleInstance;
}void SingleInstance::deleteInstance()
{std::unique_lockstd::mutex lock(m_Mutex); // 加锁if (m_SingleInstance){delete m_SingleInstance;m_SingleInstance NULL;}
}void SingleInstance::Print()
{std::cout 我的实例内存地址是: this std::endl;
}SingleInstance::SingleInstance()
{std::cout 构造函数 std::endl;
}SingleInstance::~SingleInstance()
{std::cout 析构函数 std::endl;
}
/// 加锁的懒汉式实现 //#endif静态局部变量的懒汉单例C11线程安全
//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H
#include pthread.h // pthread_create
#include iostream // std::cout
#include mutex // std::mutex
/// 内部静态变量的懒汉实现 //
class Single
{public:// 获取单实例对象static Single GetInstance();// 打印实例地址void Print();private:// 禁止外部构造Single();// 禁止外部析构~Single();// 禁止外部复制构造Single(const Single signal);// 禁止外部赋值操作const Single operator(const Single signal);
};Single Single::GetInstance()
{// 局部静态特性的方式实现单实例static Single signal;return signal;
}void Single::Print()
{std::cout 我的实例内存地址是: this std::endl;
}Single::Single()
{std::cout 构造函数 std::endl;
}Single::~Single()
{std::cout 析构函数 std::endl;
}
/// 内部静态变量的懒汉实现 //#endif饿汉式本身就线程安全
//Singleton.h
/****************************************************/
#ifndef SINGLETON_H
#define SINGLETON_H
#include pthread.h // pthread_create
#include iostream // std::cout
#include mutex // std::mutex
// 饿汉实现 /
class Singleton
{
public:// 获取单实例static Singleton* GetInstance();// 释放单实例进程退出时调用static void deleteInstance();// 打印实例地址void Print();private:// 将其构造和析构成为私有的, 禁止外部构造和析构Singleton();~Singleton();// 将其拷贝构造和赋值构造成为私有函数, 禁止外部拷贝和赋值Singleton(const Singleton signal);const Singleton operator(const Singleton signal);private:// 唯一单实例对象指针static Singleton *g_pSingleton;
};// 代码一运行就初始化创建实例 本身就线程安全
Singleton* Singleton::g_pSingleton new (std::nothrow) Singleton;Singleton* Singleton::GetInstance()
{return g_pSingleton;
}void Singleton::deleteInstance()
{if (g_pSingleton){delete g_pSingleton;g_pSingleton NULL;}
}void Singleton::Print()
{std::cout 我的实例内存地址是: this std::endl;
}Singleton::Singleton()
{std::cout 构造函数 std::endl;
}Singleton::~Singleton()
{std::cout 析构函数 std::endl;
}
// 饿汉实现 /#endif代码参考C 线程安全的单例模式总结 我这里运行结果总是有点不尽人意不知道是怎么回事所以就没放运行结果推荐看原文。
要点总结
Singleton模式中的实例构造器可以设置为protected以允许子类派生。Singleton模式一般不要支持拷贝构造函数和Clone接口因为这有可能导致多个对象实例,与Singleton模式的初衷违背。如何实现多线程环境下安全的Singleton?注意对双检查锁的正确实现。