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

饿汉

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

总结

复制代码
尽可能用内部静态变量单例
相关推荐
有位神秘人1 天前
kotlin与Java中的单例模式总结
java·单例模式·kotlin
云姜.3 天前
单例模式及线程安全问题
单例模式
木井巳3 天前
【多线程】单例模式
java·单例模式·java-ee
忧郁的Mr.Li4 天前
设计模式--单例模式
javascript·单例模式·设计模式
卷卷的小趴菜学编程4 天前
项目篇----仿tcmalloc的内存池设计(page cache)
c++·缓存·单例模式·tcmalloc·内存池·span cache
萧曵 丶5 天前
懒加载单例模式中DCL方式和原理解析
java·开发语言·单例模式·dcl
萧曵 丶5 天前
单例模式 7 种实现方式对比表
java·单例模式
当战神遇到编程9 天前
图书管理系统
java·开发语言·单例模式
Remember_9939 天前
Java 单例模式深度解析:设计原理、实现范式与企业级应用场景
java·开发语言·javascript·单例模式·ecmascript
春日见9 天前
win11 分屏设置
java·开发语言·驱动开发·docker·单例模式·计算机外设