饿汉、饱汉、内部静态变量三种单例模式

饿汉

复制代码
一个饥饿的人,看到食物就吃。
所以类加载了就创建了实例。
特点:
    1.立即创建实例
    2.线程安全
c 复制代码
// 文件: main.cc
// 时间: 2024-07-26
// 来自: ccj
// 描述: 饿汉式单例

#include <iostream>

class Singleton {
public:
    ~Singleton() { std::cout << "~Singleton()" << std::endl; }
    static Singleton& getInstance() { return instance; }

public:
    void doSomething() { std::cout << "Doing something." << std::endl; }

private:
    Singleton() { std::cout << "Singleton()" << std::endl; }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    static Singleton instance;
};

// 立即创建实例
Singleton Singleton::instance;

int main() {
    std::cout << "start use singleton" << std::endl;

    Singleton& instance1 = Singleton::getInstance();
    Singleton& instance2 = Singleton::getInstance();

    // 验证是否为同一个实例
    if (&instance1 == &instance2) {
        std::cout << "instance1 and instance2 are the same instance." << std::endl;
    }

    instance1.doSomething();
    instance2.doSomething();

    return 0;
}

饱汉/懒汉

复制代码
一个吃饱的人,食物可以放一会。
类先加载,在真正调用时创建实例
特点:
1.延时创建实例
2.加锁才能线程安全
3.每次获取单例会判断一次是否创建
4.要注意释放单例
c 复制代码
// 文件: main.cc
// 时间: 2024-07-26
// 来自: ccj
// 描述: 饱汉式单例

#include <iostream>
#include <mutex>

class Singleton {
public:
    ~Singleton() { std::cout << "~Singleton()" << std::endl; }
    static Singleton* getInstance() {
        if (instance == nullptr) {
            std::lock_guard<std::mutex> lock(mtx);
            if (instance == nullptr) { instance = new Singleton(); }
        }
        return instance;
    }

public:
    void doSomething() { std::cout << "Doing something." << std::endl; }

private:
    Singleton() { std::cout << "Singleton()" << std::endl; }
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;

private:
    static Singleton* instance;
    static std::mutex mtx;
};

// 先不创建实例
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;

int main() {
    std::cout << "start use singleton" << std::endl;

    Singleton* instance1 = Singleton::getInstance();
    Singleton* instance2 = Singleton::getInstance();

    // 验证是否为同一个实例
    if (instance1 == instance2)
        std::cout << "instance1 and instance2 are the same instance." << std::endl;

    instance1->doSomething();
    instance2->doSomething();

    // 注意: 需要自己释放
    delete Singleton::getInstance();

    return 0;
}

内部静态变量

复制代码
C++11规定了local static在多线程条件下的初始化行为,要求编译器保证了内部静态变量的线程安全性。
特点:
1.延时创建实例
2.编译器保证线程安全
c 复制代码
// 文件: main.cc
// 时间: 2024-07-26
// 来自: ccj
// 描述: 内部静态变量单例

#include <iostream>

class Singleton {
public:
    ~Singleton() { std::cout << "~Singleton()" << std::endl; }
    static Singleton &getInstance() {
        static Singleton s;
        return s;
    }

public:
    void doSomething() { std::cout << "Doing something." << std::endl; }

private:
    Singleton() { std::cout << "Singleton()" << std::endl; }
    Singleton(const Singleton &) = delete;
    Singleton &operator=(const Singleton &) = delete;
};

int main() {
    std::cout << "start use singleton" << std::endl;

    Singleton &instance1 = Singleton::getInstance();
    Singleton &instance2 = Singleton::getInstance();

    // 验证是否为同一个实例
    if (&instance1 == &instance2)
        std::cout << "instance1 and instance2 are the same instance." << std::endl;

    instance1.doSomething();
    instance2.doSomething();

    return 0;
}

总结

复制代码
尽可能用内部静态变量单例
相关推荐
程序员卷卷狗16 小时前
Java 单例模式的五种实现:饿汉式、懒汉式、DCL、静态内部类、枚举单例
java·开发语言·单例模式
SmoothSailingT17 小时前
C#——单例模式
开发语言·单例模式·c#
博语小屋2 天前
简单线程池实现(单例模式)
linux·开发语言·c++·单例模式
利刃大大2 天前
【JavaSE】十五、线程同步wait | notify && 单例模式 && 阻塞队列 && 线程池 && 定时器
java·单例模式·线程池·定时器·阻塞队列
筏.k2 天前
C++ 设计模式系列:单例模式
c++·单例模式·设计模式
席之郎小果冻4 天前
【03】【创建型】【聊一聊,单例模式】
开发语言·javascript·单例模式
fakerth4 天前
【OpenHarmony】设计模式模块详解
c++·单例模式·设计模式·openharmony
冷崖5 天前
单例模式-创建型
c++·单例模式
缪懿6 天前
javaEE:多线程,单列模式和生产者消费者模型
java·单例模式·java-ee
better_liang6 天前
每日Java面试场景题知识点之-单例模式
java·单例模式·设计模式·面试·企业级开发