多线程同步:使用 std::mutex 和 std::unique_lock 保护共享资源

news2024/11/30 14:38:30

在当今的软件开发中,多线程编程是一项至关重要的技术,它允许程序同时执行多个任务,从而提高应用程序的效率和响应速度。然而,多线程环境也带来了数据安全和一致性的挑战。在多个线程需要访问和修改同一数据资源的情况下,如果没有适当的同步机制,就可能发生竞态条件,导致数据不一致或程序行为的不确定性。为了解决这些问题,锁的概念应运而生。

锁是一种用于管理对共享资源访问的同步机制,主要用于多线程环境中保护共享资源,防止多个线程同时访问同一资源通过锁定机制,可以确保在任意时刻,只有一个线程可以访问关键的代码区域,从而维护了数据的完整性和一致性。常见的锁机制包括互斥锁(mutex)、读写锁(允许多个读操作同时进行,但写操作是独占的)和递归锁等。

 

基本概念

  • std::thread: C++标准库中的线程类,用于创建和管理线程。
  • std::mutex: 用于保护共享数据,防止多个线程同时访问同一资源。
  • std::unique_lock: 是一个RAII(资源获取即初始化)风格的mutex管理工具。它可以在构造时自动锁定关联的mutex,并在析构时自动释放mutex。

例子

目标:创建两个线程,共同操作一个共享的计数器(int类型),每个线程增加10000次计数器,使用std::mutex来同步对计数器的访问。

不使用锁的情况示例代码

首先,让我们看看在不使用互斥锁的情况下,多线程访问共享资源可能导致的问题。

#include <iostream>
#include <thread>

// 共享资源
int counter = 0;

void incrementCounter() {
    for (int i = 0; i < 10000; ++i) {
        ++counter;  // 直接修改共享资源,没有锁的保护
    }
}

int main() {
    std::thread t1(incrementCounter);
    std::thread t2(incrementCounter);

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

    std::cout << "Final counter value without mutex: " << counter << std::endl;
    return 0;
}

可能的输出

Final counter value without mutex: 13542

在这个示例中,因为两个线程都在尝试修改同一个变量而没有同步措施,所以最终的counter值并不是预期的20000,而是一个随机的值,这是因为发生了竞态条件。

使用锁的情况示例代码

现在,我们使用std::mutexstd::unique_lock来同步对共享资源的访问。

#include <iostream>
#include <thread>
#include <mutex>

// 共享资源
int counter = 0;
std::mutex mtx;

void incrementCounter() {
    for (int i = 0; i < 10000; ++i) {
        std::unique_lock<std::mutex> lock(mtx);  // 使用unique_lock来锁定mtx
        ++counter;
    }
}

int main() {
    std::thread t1(incrementCounter);
    std::thread t2(incrementCounter);

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

    std::cout << "Final counter value with mutex: " << counter << std::endl;
    return 0;
}

结果

Final counter value with mutex: 20000

在这个版本的代码中,每次修改共享资源counter时都通过std::unique_lock来确保只有一个线程可以执行这一操作。结果显示,最终的counter值正是预期的20000,说明通过锁正确地管理了线程间的资源访问。

为何不涉及变量 i

关于循环变量 i,它是每个线程的局部变量,而不是共享资源。每个线程在调用 incrementCounter 函数时都会有自己的 i 副本。因此,不需要通过互斥锁来保护对 i 的访问,因为不存在多个线程同时访问或修改同一个 i 的问题。

在多线程环境中,通常只有对共享资源的访问和修改才需要同步机制(如互斥锁)。局部变量自然地由各自的线程独立管理,不会引起线程间的冲突。

总结

在C++多线程编程中,std::mutexstd::unique_lock是保护共享数据和避免竞态条件的重要工具。通过使用std::unique_lock,可以更安全和便捷地管理锁的获取和释放,从而简化代码并减少因错误管理锁而导致的问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1602794.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【SAP NWDI】创建DC(Development component)(三)

一、准备DC组件包 首先需要下载下面这7个sca 的组件包,找到对应的ME版本的组件包,可以找对应的Basis帮忙下载。然后把这7个组件包放入到服务器中根目录的这个目录中,如果目录没有的需要自己创建出来。 二、导入DC组件包 注意:下面的的图中 有需要填写 in 和 out 的连个目…

RabbitMQ-核心特性

已经不需要为RabbitMQ交换机的离去而感到伤心了&#xff0c;接下来登场的是RabbitMQ-核心特性!!! 文章目录 核心特性消息过期机制消息确认机制死信队列 核心特性 消息过期机制 官方文档&#xff1a;https://www.rabbitmq.com/ttl.html 可以给每条消息指定一个有效期&#xf…

富文本在线编辑器 - tinymce

tinymce 项目是一个比较好的富文本编辑器. 这里有个小demo, 下载下来尝试一下, 需要配置个本地服务器才能够访问, 我这里使用的nginx, 下面是我的整个操作过程: git clone gitgitee.com:chick1993/layui-tinymce.git cd layui-tinymcewget http://nginx.org/download/nginx-1.…

监控系统泛滥:CTO 面临的隐形成本危机

在信息技术飞速发展的今天&#xff0c;构建和维护现代化的数字系统变得日益复杂和关键&#xff1b;在这样的背景下&#xff0c;监控系统的作用变得尤为突出。正如业界广泛流传的一句经验之谈“无监控&#xff0c;不运维”所揭示的道理一样&#xff0c;对于任何具有一定复杂性的…

Redis(Windows版本下载安装和使用)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

lua 光速入门

文章目录 安装注释字符串变量逻辑运算条件判断循环函数Table (表)常用全局函数模块化 首先明确 lua 和 js Python一样是动态解释性语言&#xff0c;需要解释器执行。并且不同于 Python 的强类型与 js 的弱类型&#xff0c;它有点居中&#xff0c;倾向于强类型。 安装 下载解释…

AI预测福彩3D第38弹【2024年4月17日预测--第8套算法开始计算第6次测试】

今天咱们继续测试第8套算法和模型&#xff0c;今天是第5次测试&#xff0c;目前的测试只是为了记录和验证&#xff0c;为后续的模型修改和参数调整做铺垫&#xff0c;所以暂时不建议大家盲目跟买~废话不多说了&#xff0c;直接上结果&#xff01; 2024年4月17日3D的七码预测结果…

vivado 与 VIO 核输出探针进行交互

与 VIO 核输出探针进行交互 VIO 核输出探针用于将值写入实际硬件中的 FPGA 或 ACAP 中运行的设计。 VIO 输出探针通常用作为待测设计的低带 宽控制信号。 VIO 调试探针需手动添加到 VIO 仪表板的“ VIO 探针 (VIO Probes) ”窗口中。请参阅“在‘调试探针 (Debug Pr…

中国12.5米DEM地形瓦片数据免费领取!

之前向大家公开了中国34个省12.5米DEM地形瓦片数据的免费领取链接&#xff0c;大家对12.5米DEM数据的使用需求很强烈&#xff0c;领取也很积极&#xff0c;也有不少读者反馈能否提供全国范围的12.5米DEM地形瓦片数据&#xff0c;因为分省级地形瓦片数据想要合并成全国数据&…

CUDA 以及MPI并行矩阵乘连接服务器运算vscode配置

一、CUDA Vscode配置 &#xff08;一&#xff09;扩展安装 本地安装 服务器端安装 &#xff08;二&#xff09; CUDA 配置 .vscode c_cpp_properties.json {"configurations": [{"name": "Linux","includePath": ["${workspa…

【AI】DeepStream(01)介绍

1、简介 DeepStream 本质是 GStreamer 的插件,基于GStreamer的管道,实现高效的视频流分析。 DeepStream 将来自 USB/CSI 摄像头的流数据、来自文件的视频或通过 RTSP 的流作为输入,并使用人工智能和计算机视觉从像素中生成AI结果。 DeepStream SDK 可以成为许多视频分析解…

C++ queue priority_queuestack 详解及模拟实现

1. stack的介绍和使用 1.1 stack的介绍 1. stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行元素的插入与提取操作。 2. stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容…

【华为笔试题汇总】2024-04-17-华为春招笔试题-三语言题解(Python/Java/Cpp)

&#x1f36d; 大家好这里是KK爱Coding &#xff0c;一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为近期的春秋招笔试题汇总&#xff5e; &#x1f4bb; ACM银牌&#x1f948;| 多次AK大厂笔试 &#xff5c; 编程一对一辅导 &#x1f44f; 感谢大家的订阅➕ 和 喜欢&#x1f…

吴恩达2022机器学习专项课程(一) 第二周课程实验:特征工程和多项式回归(Lab_04)

目标 探索特征工程和多项式回归&#xff0c;使用线性回归来拟合非常复杂甚至非线性的函数。 1.为什么线性回归能拟合非线性函数&#xff1f; fxw*xb&#xff0c;属于线性回归的扩展&#xff0c;这个公式在数学中不属于线性&#xff0c;因为有x&#xff0c;而在机器学习中属于…

【云计算】云数据中心网络(六):私网连接

云数据中心网络&#xff08;六&#xff09;&#xff1a;私网连接 1.什么是私网连接2.私网连接的组成3.私网连接的优势4.私网连接的主要应用场景 前面讲到 VPC 网络具有隔离性&#xff0c;VPC 之间无法通信。当一个 VPC 中的终端需要访问部署在另一个 VPC 中的服务时&#xff0c…

江苏开放大学2024年春《测试技术 060245》作业3参考答案

答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 答案&#xff1a;更多答案&#xff0c;请关注【电大搜题】微信公众号 单选题 1相关系数ρxy的取值范围处于( )之间。 A-1和0 B…

OpenCV基本图像处理操作(十一)——图像特征Sift算法

图像尺度空间 在一定的范围内&#xff0c;无论物体是大还是小&#xff0c;人眼都可以分辨出来&#xff0c;然而计算机要有相同的能力却很难&#xff0c;所以要让机器能够对物体在不同尺度下有一个统一的认知&#xff0c;就需要考虑图像在不同的尺度下都存在的特点。 尺度空间的…

WebGl/Three 粒子系统 人物破碎及还原运动

粒子 首先&#xff0c;加载模型&#xff0c;这是万千粒子的前身&#xff0c;模型对象由很多面构成&#xff0c;这些面又是由各个点构成的&#xff0c;所以可以将模型的几何体对象geometry赋给粒子对象&#xff0c;粒子物体用Points方式渲染 bloader.load("obj/female02/Fe…

斯坦福发布法律指令数据集LawInstruct,统一17个辖区24种语言

在法律领域&#xff0c;语言模型&#xff08;Language Models, LLMs&#xff09;的发展一直面临着独特的挑战。法律文本的复杂性、专业术语的广泛使用以及对精确性和可靠性的极高要求&#xff0c;使得法律领域的自然语言处理&#xff08;Natural Language Processing, NLP&…

新版周易运势风水测算 宝宝起名改名 公司吉凶测名 八字姻缘爱情算命预测 易经塔罗牌占卜

源码简介&#xff1a; 系统包含八字合婚、流年运势、宝宝起名、塔罗占卜、姓名配对、命中注定、星座运势、八字精批、桃花运姻缘、测终生运、十年大运详批、犯太岁化解、紫薇财运精批、取名改名、算姻缘、婚前合婚、算事业、算财运、姓名详批、塔罗爱情占卜&#xff08;三个月…