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

饿汉

复制代码
一个饥饿的人,看到食物就吃。
所以类加载了就创建了实例。
特点:
    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;
}

总结

复制代码
尽可能用内部静态变量单例
相关推荐
雨浓YN2 小时前
基于设计模式的Winform软件框架-01Xml\Log\Ini日志(单例模式+生产者消费者模式)
单例模式·设计模式
仙俊红1 天前
Java 单例模式:类里面为什么可以有自己类型的字段?
java·开发语言·单例模式
swordbob1 天前
prototype 注入到 singleton 里,prototype是否还是线程安全的
安全·spring·单例模式·原型模式
谁似人间西林客3 天前
工业大数据实战:看中国智造如何用数据驱动效率革命
大数据·单例模式
张小姐的猫3 天前
【Linux】多线程 —— 线程池 | 单例模式 | 常见锁
linux·运维·服务器·c++·单例模式·设计模式·策略模式
Java面试题总结4 天前
双重检验锁的单例模式在高并发下的可见性问题
单例模式
珊瑚里的鱼7 天前
手撕单例模式中的饿汉模式和懒汉模式,懒汉模式还要再多加一个C++11版本的
开发语言·c++·单例模式
韩曙亮7 天前
【Flutter】Dart 单例 ( 单例模式核心规则 | 饿汉式单例 | 懒汉式单例 | 极简空安全 懒汉式单例 | 工厂构造函数单例 )
flutter·单例模式·dart·饿汉式单例·懒汉式单例·空安全·空赋值
wunaiqiezixin9 天前
如何在C++中实现一个单例模式?
c++·单例模式
basketball6169 天前
设计模式入门:1. 单例模式详解 C++实现
c++·单例模式·设计模式