做网站域名是什么意思,网站制作教程百度云,网站首页按钮图片,网站优化课程文章目录 单例模式#xff08;Singleton Pattern#xff09;概述单例模式的实现方式及代码示例1. 饿汉式单例#xff08;在程序启动时就创建实例#xff09;2. 懒汉式单例#xff08;在第一次使用时才创建实例#xff09; 单例模式的注意事项应用场景 C代码懒汉模式-经典… 文章目录 单例模式Singleton Pattern概述单例模式的实现方式及代码示例1. 饿汉式单例在程序启动时就创建实例2. 懒汉式单例在第一次使用时才创建实例 单例模式的注意事项应用场景 C代码懒汉模式-经典版(线程不安全)经典版优化(线程安全) 内部静态变量的懒汉实现饿汉模式 单例模式Singleton Pattern概述 定义 单例模式是一种创建型设计模式它确保一个类只有一个实例并提供一个全局访问点来访问这个唯一实例。就像是在整个软件系统中某个特定的对象只能有一个并且各个部分都能方便地获取到这个唯一的对象。 作用 资源共享与协调适用于管理一些全局的资源比如数据库连接池。整个应用程序通常只需要一个数据库连接池实例来协调和管理数据库连接的分配与回收避免创建多个连接池导致资源浪费和管理混乱。状态一致性维护在某些场景下需要保证整个系统中某个对象的状态是唯一且一致的。例如系统配置类全局只有一份配置信息各个模块获取的都是同一个配置实例能保证配置的一致性防止出现因多个不同配置实例而导致的逻辑混乱。节省内存和避免重复创建对于一些创建成本较高或者占用较多系统资源的对象只创建一个实例可以避免多次重复创建带来的内存消耗和性能开销像一些复杂的日志记录类创建实例可能涉及到初始化大量的文件操作相关资源等单例模式可保证只创建一次。 单例模式的实现方式及代码示例
1. 饿汉式单例在程序启动时就创建实例
#include iostream// 饿汉式单例类
class Singleton {
private:// 将构造函数声明为私有防止外部创建实例Singleton() {std::cout 创建单例实例 std::endl;}// 静态成员变量保存唯一实例在程序启动时就初始化static Singleton* instance;
public:// 获取单例实例的静态方法static Singleton* getInstance() {return instance;}
};// 静态成员变量初始化在程序启动时就创建好实例
Singleton* Singleton::instance new Singleton;以下是使用饿汉式单例的示例代码
int main() {Singleton* s1 Singleton::getInstance();Singleton* s2 Singleton::getInstance();// 比较两个指针应该指向同一个实例if (s1 s2) {std::cout s1和s2是同一个实例 std::endl;}return 0;
}在饿汉式单例中
优点实现简单线程安全因为在程序启动时就完成了实例的创建不存在多个线程同时创建实例的竞争问题在多线程环境下也能保证只有一个实例被创建。缺点如果单例类的构造函数执行一些比较耗时或者占用大量资源的初始化操作并且这个单例可能在程序运行很久之后才会被用到那么会造成程序启动时不必要的性能开销提前占用了系统资源。
2. 懒汉式单例在第一次使用时才创建实例
#include iostream
#include mutex// 懒汉式单例类
class Singleton {
private:Singleton() {std::cout 创建单例实例 std::endl;}// 静态成员变量保存唯一实例指针static Singleton* instance;// 互斥锁用于保证多线程环境下的线程安全static std::mutex mutex_;
public:// 获取单例实例的静态方法使用了双重检查锁定DCLP来优化线程安全和性能static Singleton* getInstance() {if (instance nullptr) {std::lock_guardstd::mutex guard(mutex_);if (instance nullptr) {instance new Singleton;}}return instance;}
};// 静态成员变量初始化
Singleton* Singleton::instance nullptr;
std::mutex Singleton::mutex_;以下是使用懒汉式单例的示例代码
int main() {Singleton* s1;Singleton* s2;// 模拟多线程环境下获取单例实例std::thread t1([]() { s1 Singleton::getInstance(); });std::thread t2([]() { s2 Singleton::getInstance(); });t1.join();t2.join();if (s1 s2) {std::cout s1和s2是同一个实例 std::endl;}return 0;
}在懒汉式单例中
优点实例在第一次使用时才创建避免了程序启动时不必要的资源占用和性能开销对于那些创建成本较高且可能不会马上用到的单例对象比较合适。缺点实现相对复杂一些需要考虑多线程环境下的线程安全问题虽然使用了双重检查锁定等优化手段但如果处理不当还是可能出现问题比如内存乱序执行等情况不过现代编译器和处理器一般会有相应机制来尽量避免。
单例模式的注意事项
构造函数私有无论是饿汉式还是懒汉式都要将构造函数声明为私有这样可以防止外部代码通过常规的方式如Singleton s;这种直接实例化的语句来创建多个实例保证了单例的唯一性。线程安全问题在多线程环境下懒汉式单例需要特别注意线程安全要采用合适的同步机制如互斥锁、原子操作等来确保在多个线程同时尝试获取实例时只有一个线程能够创建实例避免创建出多个实例破坏单例模式的规则。而饿汉式单例天然具有一定的线程安全性但也需要根据具体应用场景来考虑是否满足需求。对象生命周期管理要注意单例对象的生命周期尤其是在动态内存分配如new操作符创建实例的情况下需要合理地处理实例的释放避免内存泄漏等问题。例如可以通过定义一个静态的析构函数来释放单例对象占用的资源但这需要谨慎设计防止出现意外的行为。
单例模式在很多软件系统中都有广泛应用不过也要根据实际情况合理选择合适的实现方式和注意相关的设计要点以确保其能正确地发挥作用。
应用场景
系统配置管理在一个应用程序中通常会有各种配置信息如数据库连接配置、服务器端口配置、应用程序的一些全局参数等。将这些配置信息封装在一个单例的配置类中整个系统通过唯一的实例来获取和修改配置保证了配置的一致性并且方便统一管理。日志记录器用于记录程序运行过程中的各种日志信息整个程序往往只需要一个日志记录实例来将日志输出到文件、控制台或者发送到远程日志服务器等。不同的模块都向这个唯一的日志记录器实例写入日志确保日志管理的统一性和有序性。线程池管理在多线程编程中线程池是管理和复用线程资源的重要组件。一般一个应用程序只需要一个线程池实例通过这个单例的线程池来分配线程执行任务、回收线程等避免创建多个线程池导致资源浪费和线程调度混乱。缓存机制例如网页缓存、数据库查询结果缓存等场景。以网页缓存为例一个网站服务器可以有一个单例的缓存类用于存储经常访问的网页内容下次再有相同请求时可以直接从缓存中获取减少服务器的响应时间和数据库等资源的消耗而且只有一个缓存实例方便管理缓存的有效性、容量控制等。
C代码
懒汉模式-经典版(线程不安全)
#include iostream
using namespace std;//懒汉模式
class Singleton
{
public:
/**
*需要提供要给全局访问点就需要在类中定义一个static函数返回在类内部唯一构造的实例
*/static Singleton *GetInstance(){if (m_Instance NULL ){m_Instance new Singleton ();}return m_Instance;}static void DestoryInstance(){if (m_Instance ! NULL ){delete m_Instance;m_Instance NULL ;}}private:
/**
*构造函数卸载私有里为了防止在外部调用类的构造函数而构造实例
*/Singleton();static Singleton *m_Instance;
};Singleton *Singleton ::m_Instance NULL;int main(int argc , char *argv [])
{Singleton *singletonObj Singleton ::GetInstance(); Singleton ::DestoryInstance();return 0;
}
经典版优化(线程安全)
#include iostream
using namespace std;//懒汉模式
class Singleton
{
public:
/*
此处进行了两次m_Instance NULL的判断是借鉴了Java的单例模式实现时使用的所谓的“双检锁”机制。
因为进行一次加锁和解锁是需要付出对应的代价的而进行两次判断就可以避免多次加锁与解锁操作同时也
保证了线程安全。但是这种实现方法在平时的项目开发中用的很好也没有什么问题但是如果进行大数据
的操作加锁操作将成为一个性能的瓶颈为此一种新的单例模式的实现也就出现了。
*/static Singleton *GetInstance(){if (m_Instance NULL ){Lock(); if (m_Instance NULL ){m_Instance new Singleton ();}UnLock(); }return m_Instance;}static void DestoryInstance(){if (m_Instance ! NULL ){delete m_Instance;m_Instance NULL ;}}
private:Singleton();static Singleton *m_Instance;
};Singleton *Singleton ::m_Instance NULL;int main(int argc , char *argv [])
{Singleton *singletonObj Singleton ::GetInstance();Singleton ::DestoryInstance();return 0;
}
内部静态变量的懒汉实现
此方法也很容易实现在instance函数里定义一个静态的实例也可以保证拥有唯一实例在返回时只需要返回其指针就可以了。推荐这种实现方法真得非常简单。
#include iostream
using namespace std;class Singleton
{
public:static Singleton *GetInstance(){lock();static Singleton m_Instance;unlock();return m_Instance;}
private:Singleton();};int main(int argc , char *argv [])
{Singleton *singletonObj Singleton ::GetInstance();coutsingletonObj-GetTest()endl;singletonObj Singleton ::GetInstance();coutsingletonObj-GetTest()endl;
}
饿汉模式
#include iostream
using namespace std;class Singleton
{
public:static Singleton *GetInstance(){return m_instace;}
private:Singleton();static Singleton *m_instance;};
Singleton* Singleton :: m_instance new Singleton();
int main(int argc , char *argv [])
{Singleton *singletonObj Singleton ::GetInstance();singletonObj Singleton ::GetInstance();return 0;
}