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

饿汉

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

总结

复制代码
尽可能用内部静态变量单例
相关推荐
JTCC7 小时前
Java 设计模式西游篇 - 第一回:单例模式显神通 悟空巧解资源劫
java·单例模式·设计模式
geovindu21 小时前
python: Singleton Pattern
开发语言·python·单例模式·设计模式
会员源码网21 小时前
深度解析线程安全单例模式:双重检查锁失效真相与指令重排破解方案
安全·单例模式
_OP_CHEN21 小时前
【Linux系统编程】(四十六)线程池原理与实现:从固定线程池到线程安全单例模式
linux·单例模式·操作系统·线程池·进程·线程安全·c/c++
一点多余.16 天前
java中的单例模式
java·开发语言·单例模式
NaCl鱼呜啦啦17 天前
static 实例 vs 单例模式
开发语言·单例模式
白太岁18 天前
C++:(5) 单例模式与支持初始化失败的单例模式
c++·单例模式
A懿轩A19 天前
【Java 基础编程】Java 面向对象进阶:static/final、抽象类、接口、单例模式
java·开发语言·单例模式
郝学胜-神的一滴19 天前
单例模式:从经典实现到Vibe Coding时代的思考
开发语言·c++·程序人生·单例模式·设计模式·多线程
Andy Dennis20 天前
各种单例模式的实现方式
java·单例模式