【C++】C++ 锁(std::mutex)的使用及其使用

在C++中,锁是一种同步机制,用于保护共享资源在多线程环境下的访问安全,防止因并发访问导致的数据不一致、竞态条件等问题。

以下是对C++中锁相关概念、类型以及使用方法的详细介绍:

1. 互斥锁(Mutex)

互斥锁(std::mutex)是最基础也是最常用的锁类型。它确保在同一时刻,最多只有一个线程能够获得锁并访问受保护的资源。当一个线程持有互斥锁时,其他尝试获取该锁的线程将被阻塞,直到锁被释放。

基本操作

  • 锁住(Locking):使用std::mutex::lock()方法获取锁。如果锁不可用(即已被其他线程持有),调用线程将被阻塞,直到锁变为可用。
  • 解锁(Unlocking):使用std::mutex::unlock()方法释放锁,使得等待的线程有机会获取锁并继续执行。
std::mutex mtx;
int shared_data = 0;

void thread_function() {
    std::lock_guard<std::mutex> lock(mtx); // 自动锁住和解锁
    shared_data++; // 受保护的操作
}

2. 锁的智能指针封装(常用)

为了避免忘记解锁而导致死锁,通常建议使用RAII(Resource Acquisition Is Initialization)机制来管理锁的生命周期。C++标准库为此提供了两种智能指针式的封装:

  • std::lock_guard:在构造时自动获取锁,在析构时自动释放锁。适用于函数或代码块内部,确保锁在作用域结束时正确释放。

  • std::unique_lock:比std::lock_guard更灵活,除了具备自动锁住和解锁的功能外,还支持:

    • 手动控制锁的获取和释放。
    • 非阻塞尝试锁定(try_lock())和定时尝试锁定(try_lock_for()、try_lock_until())。
    • 支持锁的转让(移动构造和赋值)。
std::mutex mtx;
int shared_data = 0;

void thread_function() {
    std::unique_lock<std::mutex> lock(mtx);
    if (some_condition) {
        lock.unlock(); // 手动释放锁
        // ... 其他操作 ...
    }
    shared_data++; // 受保护的操作
}

3. 递归锁(Recursive Mutex)

递归锁(std::recursive_mutex)允许同一线程多次获取同一个锁而不阻塞自己。这种锁适用于需要在已经持有锁的代码内部再次访问相同锁的情况。每次成功获取锁都会增加锁的递归计数,解锁时递归计数减一,直到计数降为零时锁才真正释放给其他线程。

std::recursive_mutex rmtx;
int shared_data = 0;

void recursive_function() {
    std::lock_guard<std::recursive_mutex> lock(rmtx);
    shared_data++; // 第一次获取锁
    recursive_function(); // 再次调用自己,不会阻塞,递归计数增加
} /

4. 条件变量(Condition Variables)

条件变量(std::condition_variable)与互斥锁配合使用,用于线程间的同步。它们允许线程在满足特定条件之前等待,或者通知其他线程某个条件已变为真。

td::mutex mtx;
std::condition_variable cv;
bool data_ready = false;

void producer_thread() {
    std::unique_lock<std::mutex> lock(mtx);
    // ... 生产数据 ...
    data_ready = true;
    cv.notify_one(); // 通知等待的消费者线程
}

void consumer_thread() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, [] { return data_ready; }); // 等待数据准备就绪
    // ... 消费数据 ...
}

5. 其他锁机制

  • 读写锁(std::shared_mutex / std::shared_timed_mutex):允许多个读取者同时访问资源,但同一时间只允许一个写入者。提高了读多写少场景下的并发性能。
  • 原子操作(std::atomic):对于简单数据类型的同步访问,可以使用原子操作代替锁,提供轻量级的无锁同步。

## 最佳实践

  • 最小化临界区:尽可能缩小锁保护的代码范围,以减少锁的竞争和持有时间。
  • 避免死锁:合理安排锁的获取顺序,避免循环等待;避免在持有锁时进行可能会阻塞的操作(如IO、其他锁的获取等)。
  • 使用智能指针管理锁:优先使用std::lock_guard或std::unique_lock确保锁的正确释放。
  • 考虑锁的粒度:根据实际情况选择合适的锁类型和粒度,如使用细粒度锁提高并发性,或使用粗粒度锁简化同步逻辑。

C++提供了丰富的锁机制来应对多线程编程中的同步需求,通过合理选择和使用这些工具

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ArcGIS专题图制作—3D海底地形

这一期的制图教程将带我们走入马里亚纳海沟&#xff0c;让我们一起绘制这张美妙的地图吧&#xff01;视频也上传到了B站&#xff0c;小伙伴可以去支持一下。 【制图教程】ArcGIS Pro绘制3D海底地形图 B站视频链接&#xff1a;【制图教程】ArcGIS Pro绘制3D海底地形图_哔哩哔哩…

7-31 字符串循环左移

题目链接&#xff1a;7-31 字符串循环左移 一. 题目 1. 题目 2. 输入输出样例 3. 限制 二、代码(python) 1. 代码实现 str1 input().split(\n)[0] num int(input()) len len(str1) if num > len:num num % len # 减少移动次数 print(str1[num:] str1[:num])2. 提交…

Spring Boot携手OAuth2.0,轻松实现微信扫码登录!

作者介绍&#xff1a;✌️大厂全栈码农|毕设实战开发&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。 推荐订阅精彩专栏 &#x1f447;&#x1f3fb; 避免错过下次更新 Springboot项目精选实战案例 更多项目&#xff1a;CSDN主页YAML墨韵 学如逆水行舟&#xff0c…

21.基础乐理-等音调扩展篇、为何一共十五个大调

首先 等音调 的概念是基于 等音 的概念&#xff0c;比如下图中的音名&#xff1a;因为用的按键相同&#xff0c;音名不同&#xff0c;所以被称为等音调 然后音名一共有35个&#xff0c;如下图&#xff1a;所以在理论上它会有35个大调&#xff0c;但是人总是倾向于选择简单、简洁…

关于pdf.js中文本坐标尺寸的使用

一个电子教材项目中有这样一个需求&#xff1a; 用户向网站上传一个PDF书籍后&#xff0c;网站可以对PDF书籍进行解析&#xff0c;并支持用户对PDF书籍的每一页做一些操作&#xff0c;比如&#xff1a;为英语课本的单词和句子添加音频热区。因为热区数量很多&#xff0c;所以&a…

C# 图像处理 添加水印

方法1&#xff0c;使用自带的画刷进行绘制水印 示例代码 public partial class Form1 : Form{public Form1(){InitializeComponent();}string photoPathstring.Empty;Bitmap image null;private void button1_Click(object sender, EventArgs e) //选择照片{OpenFileDialog d…

LDA主题模型

在文本挖掘领域&#xff0c;大量的数据都是非结构化的&#xff0c;很难从信息中直接获取相关和期望的信息&#xff0c;一种文本挖掘的方法&#xff1a;主题模型&#xff08;Topic Model&#xff09;能够识别在文档里的主题&#xff0c;并且挖掘语料里隐藏信息&#xff0c;并且在…

Windows 下载、安装和使用 Postman 的详细教程!

Postman 是一个功能强大的API测试工具&#xff0c;它可以帮助程序员更轻松地测试和调试 API。在本文中&#xff0c;我们将讨论如何在 Windows 上安装和使用 Postman。 安装 Postman 首先&#xff0c;让我们从 Postman 的官方网站下载并安装&#xff1a;https://www.postman.c…

YOLOV5 TensorRT部署 BatchedNMS(engine模型推理)(下)

主要是在王新宇代码的基础上改进,引入对BatchedNMS的解码 文章目录 1. 修改yolov5.cpp2.修改yololayer.h1. 修改yolov5.cpp 首先增加全局变量,名字根据转onnx时修改的节点名字来,查看onnx文件可以看到,顺序不要弄错。 const char *INPUT_NAME = “images”; const char …

C语言——贪吃蛇游戏的实现

目录 一. 贪吃蛇的介绍 二. Win32 API 1. 控制台程序 2. COORD 控制台屏幕上的坐标 3. GetStdHandle 4. GetConsoleCursorInfo CONSOLE_CURSOR_INFO 5. SetConsoleCursorInfo 6. SetConsoleCursorPosition 封装的SetPos函数 7. GetAsyncKeyState 宏定义KEY_PRESS 三…

Jackson 2.x 系列【31】Spring Boot 集成之字典回写

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Jackson 版本 2.17.0 本系列Spring Boot 版本 3.2.4 源码地址&#xff1a;https://gitee.com/pearl-organization/study-jaskson-demo 文章目录 1. 场景描述2. 案例演示2.1 修改枚举2.2 定义注解…

【Go语言】接口类型(一)接口类型与接口的值

本文是介绍golang接口类型的第一篇&#xff0c;主要介绍接口类型与接口类型的值的相关概念。 1. 静态类型、动态类型、动态值 所谓的静态类型&#xff08;即 static type&#xff09;&#xff0c;就是变量声明的时候的类型。 var age int // int 是静态类型 var name strin…

MQ面试题

为什么要使用消息队列&#xff1f; 优点&#xff1a;解耦、异步、流量削峰 缺点&#xff1a;可用性降低、复杂性提高、一致性问题 为什么选择了RabbitMQ而不是其它的MQ&#xff1f; kafka是以吞吐量高而闻名&#xff0c;不过其数据稳定性一般&#xff0c;而且无法保证消息有…

关于Android中的限定符

很多对于Android不了解或是刚接触Android的初学者来说&#xff0c;对于Android开发中出现的例如layout-large或者drawable-xxhdpi这样的文件夹赶到困惑&#xff0c;这这文件夹到底有什么用&#xff1f;什么时候用&#xff1f;这里简单的说一下。 其实&#xff0c;在上面例子中&…

day05 51单片机-外部中断、定时器

1 外部中断——按键控制LED亮灭 1.1 需求描述 本案例通过检测SW3触发的外部中断实现P00对应LED的亮灭。 1.2 硬件设计 1.2.1 中断简介 单片机中断是一种重要的计算机编程概念,用于处理在程序执行过程中突然发生的事件或条件。这些事件可以是外部硬件触发的,如按下按钮、…

SpringBoot+vue开发记录(二)

说明&#xff1a;本篇文章的主要内容为SpringBoot开发中后端的创建 项目创建: 1. 新建项目&#xff1a; 如下&#xff0c;这样简单创建就行了&#xff0c;JDK什么的就先17&#xff0c;当然1.8也是可以的&#xff0c;后面可以改。 这样就创建好了&#xff1a; 2. pom.xml…

【面试经典 150 | 回溯】电话号码的字母组合

文章目录 写在前面Tag题目来源解题思路方法一&#xff1a;回溯 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法&#xff0c;两到三天更新一篇文章&#xff0c;欢迎催更…… 专栏内容以分析题目为主&#xff0c;并附带一些对于本题涉及到的数据结构等内容进行回顾…

IOTE2024第二十一届(上海)国际物联网展览会4月24日-26日开幕

交流产业信息&#xff0c;把脉发展方向&#xff0c;IOTE 国际物联网展是每年物联网行业、企业、用户交流合作的大型平台。2024年4月24-26日IOTE2024第二十一届国际物联网展•上海站&#xff0c;在上海世博展览馆开展。 本次物联网展汇聚全球超300家参展企业、3万来自工业、物流…

区块链技术与应用学习笔记(1-4节)——北大肖臻课程

目录 1. 区块链初识(课程简介&#xff09; 被过度炒作&#xff0c;落地应用有限&#xff1f; 下一代的价值互联网&#xff1f;世界上最慢的数据库&#xff1f; 2. BTC-密码学原理&#xff08;比特币&#xff09; 1)哈希 哈希函数特点 个人学习所得 2)签名 个人对于…

工业测径仪的应用场景和可靠性判断

关键字:线缆测径仪,圆棒测径仪,圆管测径仪,金属棒管测径仪,工业测径仪,智能测径仪 智能测径仪主要应用于以下领域&#xff1a; 金属加工&#xff1a;测量金属线材、棒材、管材等的直径。线缆制造&#xff1a;检测电线、电缆的直径。塑料管材生产&#xff1a;监控塑料管材的外…