什么是单例模式

单例模式就是 只有一个 不能存在多个

  1. 饿汉式单例模式

    • 实现方式 :
      • 这种模式在程序启动或单例类被加载时就创建好实例。例如,以下是一个简单的 C++ 实现的饿汉式单例类,用于记录日志(假设这个日志类在整个程序中有且仅有一个实例):
        *

        复制代码
          class Logger {
          public:
              static Logger& getInstance() {
                  return instance;
              }
              void log(const std::string& message) {
                  // 这里可以实现将消息记录到文件或其他输出方式的逻辑
                  std::cout << "Log: " << message << std::endl;
              }
          private:
              static Logger instance;
              Logger() {}
              Logger(const Logger&) = delete;
              Logger& operator=(const Logger&) = delete;
          };
          Logger Logger::instance;
      • 在这个例子中,Logger 类有一个私有的静态成员变量 instance,在类外进行初始化。getInstance 函数用于获取单例实例,它直接返回这个已经创建好的静态实例。构造函数被设为私有,这样可以防止外部代码直接创建 Logger 类的实例。同时,拷贝构造函数和赋值运算符重载函数被删除(= delete),这是为了防止通过拷贝或赋值操作产生多个实例。

    • 优缺点 :
      • 优点 :
        • 实现简单,在多线程环境下是线程安全的。因为实例是在程序启动时就创建好的,不存在多个线程同时创建实例的竞争情况。
        • 调用 getInstance 函数获取实例时速度很快,因为实例已经创建好,不需要进行实例的初始化操作。
      • 缺点 :
        • 可能会导致资源浪费。如果单例类的实例占用较多资源,并且在程序运行过程中可能并不需要立即使用这个实例,那么在程序启动时就创建实例可能会占用不必要的内存等资源。
  2. 懒汉式单例模式(线程不安全版本)

    • 实现方式 :
      • 懒汉式单例模式是在第一次 调用 getInstance 函数时才创建实例。以下是一个简单的线程不安全的懒汉式单例实现:
        *

        复制代码
          class Singleton {
          public:
              static Singleton* getInstance() {
                  if (instance == nullptr) {
                      instance = new Singleton;
                  }
                  return instance;
              }
              void doSomething() {
                  // 这里可以实现单例类的功能逻辑
              }
          private:
              static Singleton* instance;
              Singleton() {}
              Singleton(const Singleton&) = delete;
              Singleton& operator=(const Singleton&) = delete;
          };
          Singleton* Singleton::instance = nullptr;
      • 在这个例子中,getInstance 函数在每次调用时会先检查静态指针变量 instance 是否为 nullptr。如果是,则创建一个新的 Singleton 实例并赋值给 instance,然后返回这个实例。否则,直接返回已经存在的实例。同样,构造函数是私有的,并且禁止了拷贝构造和赋值操作。

    • 优缺点 :
      • 优点 :
        • 可以延迟实例的创建,只有在真正需要使用实例时才会创建,避免了资源的过早占用。
      • 缺点 :
        • 在多线程环境下是不安全的。如果多个线程同时调用 getInstance 函数,并且在实例尚未创建时,可能会导致多个线程都创建实例,违背了单例模式的原则。
  3. 懒汉式单例模式(线程安全版本)

    • 实现方式(使用互斥锁) :
      • 为了在多线程环境下保证懒汉式单例模式的正确性,可以使用互斥锁来保护实例的创建过程。以下是一个使用 C++ 标准库中的互斥锁(mutex)实现的线程安全的懒汉式单例:
        *

        复制代码
          #include <iostream>
          #include <mutex>
          class ThreadSafeSingleton {
          public:
              static ThreadSafeSingleton* getInstance() {
                  std::lock_guard<std::mutex> guard(mutex_);
                  if (instance == nullptr) {
                      instance = new ThreadSafeSingleton;
                  }
                  return instance;
              }
              void doSomething() {
                  // 这里可以实现单例类的功能逻辑
              }
          private:
              static ThreadSafeSingleton* instance;
              static std::mutex mutex_;
              ThreadSafeSingleton() {}
              ThreadSafeSingleton(const ThreadSafeSingleton&) = delete;
              ThreadSafeSingleton& operator=(const ThreadSafeSingleton&) = delete;
          };
          ThreadSafeSingleton* ThreadSafeSingleton::instance = nullptr;
          std::mutex ThreadSafeSingleton::mutex_;
      • 在这个例子中,在 getInstance 函数中添加了一个互斥锁保护。std::lock_guard<std::mutex> 是一个 RAII(Resource Acquisition Is Initialization)机制的类,它在构造时会自动获取互斥锁(mutex_),在析构时会自动释放互斥锁。这样,当多个线程同时调用 getInstance 函数时,只有一个线程能够获取锁并进行实例创建操作,其他线程会阻塞等待,从而保证了单例模式的正确性。

      • RAll 即强调资源(如内存、文件句柄、锁等)的获取与对象的初始化过程紧密结合,通过对象的构造函数获取资源,然后通过析构函数自动释放资源,以此来管理资源的生命周期。

    • 优缺点 :
      • 优点 :
        • 实现了延迟加载,并且在多线程环境下是安全的。
      • 缺点 :
        • 使用互斥锁会带来一定的性能开销。每次调用 getInstance 函数都需要获取和释放锁,在高并发场景下可能会影响程序的性能。不过,这种性能开销通常是可以接受的,因为单例实例的创建操作一般不会频繁发生。
相关推荐
蹊黎28 分钟前
C++中vector类的部分简单实现
开发语言·c++·visual studio
半个落月6 小时前
LangChain Agent 中间件实战(上):生命周期、状态、短路与工具包
javascript·langchain
半个落月6 小时前
LangChain Agent 中间件实战(下):DeepAgents文件权限、长期记忆与对话摘要
javascript·langchain
程序猿追6 小时前
kotlin-retry 接入鸿蒙后,怎样确认它真的会停止重试
开发语言·kotlin·harmonyos
我是人✓7 小时前
Java文件上传三方式对比:从传统到SpringBoot
java·开发语言
智能直播7 小时前
网络RTMP拉流不卡顿、声音不同步,一文讲透缓冲区、时间戳
开发语言·ffmpeg·php·音视频·视频编解码
墨云安全7 小时前
内网资产无法暴露到公网,怎么做安全检测?2026 年内网渗透测试的落地路径
开发语言·安全·网络安全·渗透测试·php
u0111026758 小时前
JPG、PNG、WebP 怎么选?按透明度、体积和使用场景做判断
前端·javascript·vue.js·图像处理·ai作画
摇滚侠8 小时前
《计算机是如何工作的:人人都能懂的计算机软硬件工作原理》第 9 章 机器码与汇编语言 阅读笔记 9
java·开发语言·笔记
Cc.Y8 小时前
Java零基础入门:深入Java核心:文件IO与序列化全解
java·开发语言·python