从C++单例模式到线程安全详解

C++单例模式到线程安全详解

什么是单例模式

单例模式是一种设计模式,它允许一个类只创建一个实例,同时提供一个访问该实例的全局节点。这种模式常用于控制特定资源的访问,如数据库或者网络连接。

C++实现单例模式

在C++中,实现单例模式最常用的方法是使用静态成员变量和私有构造函数。具体实现步骤如下:
1. 将类的构造函数设置为私有。
2. 在类中定义一个静态私有成员变量,用于存储唯一实例。
3. 提供一个静态公有方法用于获取该唯一实例,如果唯一实例未创建,则先创建并返回该实例。

下面是一个简单的示例代码:

class Singleton {
public:
    static Singleton& getInstance() {
        static Singleton instance;
        return instance;
    }

private:
    Singleton() {} // 禁止外部调用构造函数
    ~Singleton() {}
    Singleton(const Singleton&) = delete; // 禁止拷贝构造函数
    Singleton& operator=(const Singleton&) = delete; // 禁止赋值构造函数
};

单例模式的线程安全问题

在单线程环境下,上述实现单例模式方法是可行的。然而,在多线程环境下,上述实现会存在线程安全问题。

例如,当有多个线程同时调用getInstance()方法时,会导致创建多个实例。这违反了单例模式的定义。

解决单例模式线程安全问题的方法

想要解决单例模式的线程安全问题,需要实现双重锁定。

具体实现步骤如下:
1. 将类的构造函数设置为私有。
2. 在类中定义一个静态私有成员变量,用于存储唯一实例。
3. 提供一个静态公有方法用于获取该唯一实例,并使用双重锁定确保线程安全。

下面是一个示例代码:

#include <mutex>

class Singleton {
public:
    static Singleton& getInstance() {
        if (instance_ == nullptr) {
            std::lock_guard<std::mutex> lock(mutex_);
            if (instance_ == nullptr) {
                instance_ = new Singleton();
            }
        }
        return *instance_;
    }

private:
    Singleton() {} // 禁止外部调用构造函数
    ~Singleton() {}
    Singleton(const Singleton&) = delete; // 禁止拷贝构造函数
    Singleton& operator=(const Singleton&) = delete; // 禁止赋值构造函数

    static Singleton* instance_; // 静态成员变量
    static std::mutex mutex_; // 互斥锁
};

Singleton* Singleton::instance_ = nullptr;
std::mutex Singleton::mutex_;

在这个示例代码中,我们使用了std::mutex类型的互斥锁来保证线程安全。当getInstance()方法被第一个线程调用时,会获取到互斥锁,接着检查实例是否为空。如果为空,则创建一个新的实例,并将其赋值给instance_。最后,返回该实例。

示例说明

下面提供两个示例说明。

示例1:多线程输出单例模式的唯一实例

下面是一个多线程输出单例模式的唯一实例的示例代码:

#include <iostream>
#include <thread>

void printInstance(int tid) {
    auto& instance = Singleton::getInstance();
    std::cout << "Thread ID: " << tid << " Singleton instance address: " << &instance << std::endl;
}

int main() {
    std::thread t1(printInstance, 1);
    std::thread t2(printInstance, 2);
    std::thread t3(printInstance, 3);

    t1.join();
    t2.join();
    t3.join();

    return 0;
}

在这个示例代码中,我们定义了一个输出单例模式唯一实例地址的函数printInstance(),并分别启动了3个线程来调用该函数。通过查看输出结果,可以发现3个线程输出的唯一实例地址相同,表明单例模式的确实现了实例的唯一性。

示例2:单例模式的线程安全问题

下面是一个多线程创建单例实例的示例代码:

#include <iostream>
#include <thread>

void createInstance(int tid) {
    // 由于没有双重锁定,线程会创建多个实例
    auto& instance = Singleton::getInstance();
    std::cout << "Thread ID: " << tid << " Singleton instance address: " << &instance << std::endl;
}

int main() {
    std::thread t1(createInstance, 1);
    std::thread t2(createInstance, 2);
    std::thread t3(createInstance, 3);

    t1.join();
    t2.join();
    t3.join();

    return 0;
}

在这个示例代码中,我们定义了一个创建单例实例的函数createInstance(),并分别启动了3个线程来调用该函数。通过查看输出结果,可以发现3个线程创建的实例地址不同,表明单例模式存在线程安全问题。

总结

单例模式是一种常用的设计模式,可以保证程序中某些资源的唯一性。在多线程环境中,为了解决单例模式的线程安全问题,需要使用双重锁定的方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:从C++单例模式到线程安全详解 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • Octane Render渲染器C4D R17-19汉化破解详细教程(附完整下载)

    Octane Render渲染器C4D R17-19汉化破解详细教程 1. 下载Octane Render插件 Octane Render插件可以在官方网站上免费下载。下载链接:https://home.otoy.com/render/octane-render/ 请根据自己的操作系统和Cinema 4D版本选择下载相应的插件,下载完成后,解压缩文件。 2.…

    C 2023年5月22日
    00
  • C++ OpenCV实现图像双三次插值算法详解

    C++ OpenCV实现图像双三次插值算法的攻略如下: 1. 阅读关于双三次插值算法的资料 双三次插值是一种常见的图像缩放算法,它可以将一张低分辨率的图像缩放到更高分辨率,而不会产生锯齿或失真。 2. 安装OpenCV并编译环境 安装OpenCV并配置好编译环境,这里以Visual Studio为例。能够正常编译运行OpenCV的程序。 3. 创建一个空白的…

    C 2023年5月22日
    00
  • 基于C语言实现个人通讯录管理系统

    基于C语言实现个人通讯录管理系统攻略 1. 开发环境和工具 操作系统:Windows或Linux IDE:Visual Studio Code、Code::Blocks、Dev-C++等 编程语言:C语言 2. 需求分析 通讯录管理系统用于存储个人通讯信息,包括姓名、电话、地址等。通讯录管理系统可以实现添加、删除、修改、查找、显示等功能。 3. 设计思路 定…

    C 2023年5月30日
    00
  • cmake跨平台构建工具的学习笔记

    CMake跨平台构建工具的学习笔记 简介 CMake是一个跨平台的构建工具,可以自动生成Makefile、Visual Studio等工程文件,支持多种编程语言,包括C、C++、Java等。CMake语法简单、易读、易写,适合中小型项目的构建。 安装CMake 在官网 https://cmake.org/download/ 上下载适合自己系统的CMake安装…

    C 2023年5月23日
    00
  • 超详细VScode调试教程tasks.json和launch.json的设置

    针对“超详细VScode调试教程tasks.json和launch.json的设置”的完整攻略,我将分为以下四个部分进行讲解: 简介 tasks.json的设置 launch.json的设置 示例说明 1. 简介 VScode是广受开发者欢迎的一款编辑器,其中调试功能让我们在开发过程中可以更直观地查看程序运行过程。而tasks.json和launch.jso…

    C 2023年5月23日
    00
  • C语言实现猜拳游戏

    C语言实现猜拳游戏 简介 猜拳游戏是一种经典的多人休闲竞技游戏,通过手势的不同进行猜拳比赛。C语言可以用来实现猜拳游戏,下面就来介绍一下C语言实现猜拳游戏的方法。 实现步骤 定义变量 首先,我们需要定义一些变量,包括玩家与电脑的手势、输赢情况等信息。 int player; int computer; int result; 玩家输入 接着,需要让玩家输入一…

    C 2023年5月23日
    00
  • C++中string使用+号与int拼接方式

    下面我将详细介绍C++中string使用+号与int拼接方式的攻略。 方式一:利用to_string()函数将int转为string类型 C++中,string类型可以通过在字符串后面直接添加“+”操作符的方式与另一个字符串或字符进行拼接,但无法直接与int类型拼接。在这种情况下,我们需要先将int类型转换为string类型,然后再进行拼接。 具体的步骤如下…

    C 2023年5月22日
    00
  • C 程序 十进制转换为二进制

    下面是关于如何将C程序的十进制转换为二进制的完整使用攻略,具体内容如下: 目标 本文将介绍如何将十进制转换为二进制,并提供两个示例来演示转换过程。 步骤 根据十进制数除以 2 的规则,得到商和余数。余数只能是 0 或 1,商则继续除以2直到商为0。 从下往上写出余数,得到二进制结果。 示例1 问题 请将 10 转换为二进制。 解决方案 将 10 除以 2,得…

    C 2023年5月9日
    00
合作推广
合作推广
分享本页
返回顶部