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

文章目录

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;
相关推荐
十五年专注C++开发8 分钟前
C++类型转换通用接口设计实现
开发语言·c++·跨平台·类设计
胡萝卜3.028 分钟前
掌握string类:从基础到实战
c++·学习·string·string的使用
江公望41 分钟前
通过QQmlExtensionPlugin进行Qt QML插件开发
c++·qt·qml
Syntech_Wuz1 小时前
从 C 到 C++:容器适配器 std::stack 与 std::queue 详解
数据结构·c++·容器··队列
天才测试猿2 小时前
WebUI自动化测试:POM设计模式全解析
自动化测试·软件测试·python·selenium·测试工具·设计模式·测试用例
艾莉丝努力练剑2 小时前
【C++STL :stack && queue (一) 】STL:stack与queue全解析|深入使用(附高频算法题详解)
linux·开发语言·数据结构·c++·算法
胡萝卜3.02 小时前
深入理解string底层:手写高效字符串类
开发语言·c++·学习·学习笔记·string类·string模拟实现
kyle~2 小时前
计算机系统---CPU的进程与线程处理
linux·服务器·c语言·c++·操作系统·计算机系统
Asort2 小时前
JavaScript设计模式(十三)——责任链模式:构建灵活高效的请求处理链
前端·javascript·设计模式
笨手笨脚の2 小时前
设计模式-访问者模式
设计模式·访问者模式·行为型设计模式