单例模式---线程安全实现

文章目录

1.单例模式的特点😊

1.全局只有一个类的static实例存在;

2.不允许直接实例化,构造函数为私有的,只通过一个类的静态方法获取该实例;

2.单例模式两种实现🤣🤗😊

2.1 饿汉式

饿汉式是在类加载的时候就会创造实例,会造成资源的浪费。 具体:内部先定义并初始化好了一个静态实例。获取方法中直接返回实例。

特点:线程安全,会造成资源浪费

实现:

cpp 复制代码
class Singleton {
private:
    static Singleton instance;

    // 私有构造函数,防止类外实例化对象
    Singleton() {}

public:
    // 获取实例的静态方法
    static Singleton& getInstance() {
        return instance;
    }

    // 其他成员函数
    void doSomething() {
        // do something
    }
};

// 静态成员变量需要在类外初始化
Singleton Singleton::instance;

int main() {
    // 获取单例对象实例
    Singleton& singleton = Singleton::getInstance();
    // 调用单例对象的方法
    singleton.doSomething();

    return 0;
}

2.2 懒汉式

懒汉式是在需要时才创建实例,通过获取实例方法获取实例。

具体:内部定义一个静态实例,获取方法中判断实例是否为空,空则初始化实例;否则返回该实例

特点:避免资源浪费,造成线程安全问题。

实现

cpp 复制代码
class Singleton {
private:
    // 静态成员变量,用于保存单例实例
    static Singleton* instance;
    
    // 构造函数私有化,防止外部创建实例
    Singleton() {}
    
public:
    // 静态成员函数,用于获取单例实例
    static Singleton* getInstance() {
        // 判断实例是否为空,如果为空则创建实例
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
    
    // 删除拷贝构造函数和拷贝赋值运算符,防止被复制
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

Singleton* Singleton::instance = nullptr;  // 初始化静态成员变量

int main() {
    // 获取单例实例
    Singleton* singleton1 = Singleton::getInstance();
    Singleton* singleton2 = Singleton::getInstance();
    
    // 判断两个实例是否相同
    if (singleton1 == singleton2) {
        cout << "两个实例相同" << endl;
    } else {
        cout << "两个实例不相同" << endl;
    }
    
    return 0;
}

3.传统单例模式的线程安全问题

饿汉式是线程安全的,懒汉式不是

当多线程执行getInstance时候,如果线程A判断当前实例为空,线程B正好判断到也为空,就会申请资源;当线程A恢复了后,继续执行,也会申请内存空间;就会出现两个实例,这就会出现问题;

4.解决方法

4.1静态局部变量

cpp 复制代码
class Singleton {
private:
    Singleton() {}
    
public:
    static Singleton* getInstance() {
        static Singleton instance;
        return &instance;
    }
};

4.2加锁

cpp 复制代码
class Singleton {
private:
    // 静态成员变量,用于保存单例实例
    static Singleton* instance;
    
    // 构造函数私有化,防止外部创建实例
    Singleton() {}
    
public:
    // 静态成员函数,用于获取单例实例
    static Singleton* getInstance() {
        // 判断实例是否为空,如果为空则创建实例
        Mutexlock lock(mutex);//加锁
        if (instance == nullptr) {
            instance = new Singleton();
        }
        return instance;
    }
    
    // 删除拷贝构造函数和拷贝赋值运算符,防止被复制
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

Singleton* Singleton::instance = nullptr;  // 初始化静态成员变量

int main() {
    // 获取单例实例
    Singleton* singleton1 = Singleton::getInstance();
    Singleton* singleton2 = Singleton::getInstance();
    
    // 判断两个实例是否相同
    if (singleton1 == singleton2) {
        cout << "两个实例相同" << endl;
    } else {
        cout << "两个实例不相同" << endl;
    }
    
    return 0;
}

4.3双重检查锁(DCL)

cpp 复制代码
class Singleton {
private:
    // 静态成员变量,用于保存单例实例
    static Singleton* instance;
    
    // 构造函数私有化,防止外部创建实例
    Singleton() {}
    
public:
    // 静态成员函数,用于获取单例实例
    static Singleton* getInstance() {
        // 判断实例是否为空,如果为空则创建实例
        if (instance == nullptr) {
        Mutexlock lock(mutex);
        if(instance==nullptr)
            instance = new Singleton();
        }
        return instance;
    }
    
    // 删除拷贝构造函数和拷贝赋值运算符,防止被复制
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
};

Singleton* Singleton::instance = nullptr;  // 初始化静态成员变量

int main() {
    // 获取单例实例
    Singleton* singleton1 = Singleton::getInstance();
    Singleton* singleton2 = Singleton::getInstance();
    
    // 判断两个实例是否相同
    if (singleton1 == singleton2) {
        cout << "两个实例相同" << endl;
    } else {
        cout << "两个实例不相同" << endl;
    }
    
    return 0;
}

4.4pthread_once

cpp 复制代码
#include<iostream>
class singleton{
public:
static singleton& getinstance()
{
pthread_once(&ponce,init);//保证该函数只被执行一次
return instance;
}
private:
static void init()
{
instance=new singleton();
}
singleton(){}
~singleton(){}
static pthread_once_t  ponce;
static singleton* instance;
};
singleton::ponce=PTHREAD_ONCE_INIT;
singleton::instance=nullptr;
相关推荐
hjjdebug24 分钟前
c++中的enum变量 和 constexpr说明符
c++·enum·constexpr
何其有幸.38 分钟前
实验6-3 使用函数求特殊a串数列和(PTA|C语言)
c语言·数据结构·算法
CoderCodingNo1 小时前
【GESP】C++二级真题 luogu-B4259 [GESP202503 二级] 等差矩阵
java·c++·矩阵
明月看潮生1 小时前
青少年编程与数学 02-018 C++数据结构与算法 11课题、分治
c++·算法·青少年编程·编程与数学
冰茶_1 小时前
C#中常见的设计模式
java·开发语言·microsoft·设计模式·微软·c#·命令模式
Echo``1 小时前
2:QT联合HALCON编程—图像显示放大缩小
开发语言·c++·图像处理·qt·算法
.似水2 小时前
2025.4.22_C_可变参数列表
java·c语言·算法
Niuguangshuo2 小时前
Python 设计模式:访问者模式
python·设计模式·访问者模式
不当菜虚困2 小时前
JAVA设计模式——(七)代理模式
java·设计模式·代理模式
想睡hhh3 小时前
c++STL——stack、queue、priority_queue的模拟实现
开发语言·c++·stl