C++中互斥量、锁有什么用?

文章目录

    • 互斥量
      • 如何理解互斥量
      • C++ 中互斥量的用法
        • 基本锁定和解锁
        • 使用 `std::lock_guard` 自动管理锁
        • 使用 `std::unique_lock` 获得更多控制
      • 注意事项
    • 几种不同类型的锁

创建一个C++线程需要传入几个参数?
如何理解和使用C++线程循环
C++ 类 函数 变量 进程 线程
C++关于锁和互斥量你真的理解了吗
C++ 代码中如何使用互斥锁std::mutex和独占锁std::unique_lock

互斥量

在 C++ 中,互斥量(Mutex,即 Mutual Exclusion)是并发编程中的一种基本工具,用于控制多个线程对共享资源的访问,以防止数据竞争和相关的未定义行为。互斥量提供了一种机制,允许一个线程一次只锁定一次资源,确保在该线程释放互斥量之前,其他线程不能访问被保护的资源。

如何理解互斥量

互斥量可以被视为一种锁,用来保护共享数据,确保在任何时候只有一个线程可以访问这些数据。当一个线程需要访问被互斥量保护的资源时,它必须先锁定(acquire)这个互斥量。如果互斥量已被另一个线程锁定,该线程将被阻塞,直到互斥量被释放(unlock)。这防止了多个线程同时读写同一数据,从而防止了数据损坏和不一致性。

C++ 中互斥量的用法

C++ 标准库提供了 <mutex> 头文件,其中包含用于管理互斥量的类。最常用的类是 std::mutex。以下是 std::mutex 的基本用法:

基本锁定和解锁
#include <iostream>
#include <mutex>std::mutex mtx; // 定义一个互斥量void function() {mtx.lock();   // 锁定互斥量// ... 执行需要互斥的操作 ...mtx.unlock(); // 解锁互斥量
}
#include <iostream>
#include <mutex>std::mutex mtx; // 全局互斥锁void print_function(const std::string& message) {mtx.lock(); // 手动锁定std::cout << message << std::endl;mtx.unlock(); // 手动解锁
}int main() {print_function("Hello from main function");return 0;
}
  • main 函数直接调用 print_function,而不是创建新线程来调用它。
  • print_function 依然使用 mtx.lock()mtx.unlock() 来手动管理互斥锁,尽管在单线程环境中这实际上是不必要的。

请注意,在单线程程序中使用互斥锁通常是没有必要的,因为没有并发访问共享资源的风险。此示例仅用于说明如何单独使用 std::mutex。在实际应用中,您应该根据程序的并发需求来决定是否使用互斥锁。

使用 std::lock_guard 自动管理锁

为了避免忘记解锁或在异常发生时遗漏解锁,可以使用 std::lock_guard,它提供了一种自动管理锁的方法(RAII,资源获取即初始化)。

void safe_function() {std::lock_guard<std::mutex> lock(mtx);// ... 执行需要互斥的操作 ...
} // `lock_guard` 在作用域结束时自动释放互斥量
使用 std::unique_lock 获得更多控制

std::unique_lock<std::mutex> 提供了比 std::lock_guard 更多的灵活性,允许你延迟锁定,重复锁定和解锁,以及移动锁。

void flexible_function() {std::unique_lock<std::mutex> lock(mtx, std::defer_lock);// ... 这里互斥量还未锁定 ...lock.lock(); // 手动锁定// ... 执行需要互斥的操作 ...lock.unlock(); // 可以手动解锁// ... 可以在不同的时间点再次锁定 ...
}

注意事项

  • 避免死锁:确保在所有路径上,无论是正常还是异常,锁都能被释放。std::lock_guardstd::unique_lock 在这方面非常有用。
  • 锁的粒度:锁应该保护的是访问共享资源的最小必要代码区域,以避免不必要的性能损失。
  • 不要过度使用互斥量:在不需要保护共享资源的地方不要使用互斥量,以免引入不必要的性能开销和复杂性。

正确地使用互斥量可以确保多线程程序的正确性和稳定性,但需要谨慎使用以避免常见的陷阱,如死锁和性能瓶颈。

几种不同类型的锁

在 C++ 中,除了 std::mutex,标准库提供了几种不同类型的锁,以适应不同的并发和同步需求。下面是一些常见的锁类型及其简要说明:

  1. std::mutex:

    • 最基本的互斥锁,用于保护共享数据,防止多个线程同时访问。std::mutex 提供了基本的锁定和解锁功能,但没有递归锁定的能力。
  2. std::recursive_mutex:

    • 递归互斥锁,允许同一线程多次获取锁。如果一个线程已经持有该锁,它可以再次锁定而不会产生死锁。这对于递归函数或可重入函数很有用。
  3. std::timed_mutex:

    • 带有超时功能的互斥锁。它允许尝试锁定一个互斥锁直到指定的时间点或者经过指定的时间段。如果在指定时间内无法获得锁,则返回。
  4. std::recursive_timed_mutex:

    • 结合了 std::recursive_mutexstd::timed_mutex 的特性。它是一个可以由同一线程多次锁定的互斥锁,同时提供了带超时的锁定尝试。
  5. std::shared_mutex (C++17):

    • 允许多个线程同时读取共享数据,但写操作是互斥的。这对于读多写少的场景非常有用。
  6. std::shared_timed_mutex (C++14):

    • std::shared_mutex 的一个变体,提供了超时功能。它允许多个线程同时进行读取操作,但写入操作将独占锁定。
  7. std::lock_guard:

    • 是一个作用域锁,它在构造时自动锁定给定的互斥锁,并在析构时自动解锁。它提供了一种方便的方式来确保在作用域结束时释放互斥锁。
  8. std::unique_lock:

    • std::lock_guard 更灵活的作用域锁。它不仅允许在构造时延迟锁定,还可以在生命周期内多次锁定和解锁互斥锁。

这些锁的选择和使用取决于特定的应用场景和性能要求。例如,对于简单的互斥需求,std::mutexstd::lock_guard 通常就足够了。而对于需要更精细控制的场景,如需要超时或递归锁定功能,你可能需要选择 std::timed_mutexstd::recursive_mutex 等更高级的锁类型。

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

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

相关文章

Modbus 通信协议 二

Modbus 常用缩写 通用Modbus帧结构 -应用数据单元&#xff08;ADU&#xff09; Modbus数据模型 Modbus ADU 和 PDU 的长度 Modbus PDU结构 串行链路上的 Modbus 帧结构 Modbus 地址规则 ASCLL 模式 和 RTU 模式的比较 RTU 模式 RTU 模式位序列 帧格式 帧的标识与鉴别 CRC 循环冗…

openGauss学习笔记-183 openGauss 数据库运维-升级-升级操作

文章目录 openGauss学习笔记-183 openGauss 数据库运维-升级-升级操作183.1 就地升级和灰度升级操作步骤 openGauss学习笔记-183 openGauss 数据库运维-升级-升级操作 介绍就地升级、灰度升级和滚动升级的详细操作。 183.1 就地升级和灰度升级操作步骤 以root身份登录节点。 …

关于数据降维的几种方法

1.什么是数据降维&#xff1f; 数据降维是指将高维数据转化为低维数据的过程。在现实生活中&#xff0c;我们常常面临高维数据的问题&#xff0c;例如图像数据、文本数据、传感器数据等。高维数据在存储、处理和可视化方面都具有挑战性&#xff0c;而且可能导致过拟合问题。 …

如何使用LightsOut生成经过混淆处理的DLL

关于LightsOut LightsOut是一款功能强大的DLL生成工具&#xff0c;该工具可以帮助广大研究人员轻松生成经过混淆处理的DLL。该工具专为红队研究人员设计&#xff0c;生成的DLL可以在研究人员尝试绕过反病毒产品时禁用AMSI和ETW&#xff0c;从而更好地测试目标系统的安全性。 …

Gin 集成 prometheus 客户端实现注册和暴露指标

前言 当我们构建一个 Web 应用程序时&#xff0c;了解应用程序的性能和行为是非常重要的。Prometheus 是一个流行的开源监控系统&#xff0c;它提供了强大的指标收集和查询功能&#xff0c;可以帮助我们监控应用程序的各个方面。 在 Gin 中集成 Prometheus 可以让我们更方便地监…

Scrapy 1.3.0 使用简介

scrapy 1.3.0 python 2.7 创建一个项目&#xff1a; Before you startscraping, you will have to set up a new Scrapy project. Enter a directory whereyou’d like to store your code and run: scrapy startproject tutorial 然后就会得到一系列文件&#xff1a; 第一个爬…

使用Matplotlib绘制模拟上海城市气温变化图

模拟上海气温变化折线图 实现步骤 准备数据创建画布绘制图像显示图像 基本实现 示例代码&#xff1a; import matplotlib.pyplot as plt import random# 准备数据 x range(60) y_shanghai [random.uniform(15,18) for _ in x]# 创建画布 plt.figure(figure(20,8), dpi10…

Java 基础学习(十九)网络编程、反射

1 Socket编程 1.1 Socket编程概述 1.1.1 Socket简介 在网络编程中&#xff0c;Socket&#xff08;套接字&#xff09;是一种抽象概念&#xff0c;它用于在不同计算机之间进行通信。Socket可以看作是一种通信的端点&#xff0c;可以通过Socket与其他计算机上的程序进行数据传…

angular-tree-component组件中实现特定节点自动展开

核心API 都在 expandToNode这个函数中 HTML treeData的数据结构大概如下 [{"key": "3293040275","id": "law_category/3293040275","name": "嘿嘿嘿嘿","rank": 0,"parentKey": "0&q…

盛最多水的容器(力扣11题)

例题&#xff1a; 分析&#xff1a; 这道题给出了一个数组&#xff0c;数组里的元素可以看成每一个挡板&#xff0c;要找到哪两个挡板之间盛的水最多&#xff0c;返回盛水量的最大值。这其实是一个双指针问题。 我们可以先固定第一个挡板( i )和最后一个挡板( j )&#xff0c…

gitee创建仓库

描述 本文章记录了怎么在gitee上创建项目&#xff0c;以及使用vscode提代码到远程呢个仓库&#xff0c;如何创建一个新分支&#xff0c;并将新分支提交到远程仓库。 1、创建远程仓库 在创建远程仓库之前要先进行ssh密钥的设置 &#xff08;1&#xff09;打开黑窗口&#xff…

计算机丢失mfc110.dll的5种常用解决方法分享

丢失动态链接库文件&#xff08;DLL&#xff09;是比较常见的一种情况&#xff0c;其中之一就是“计算机丢失mfc110.dll”。这个问题通常是由于系统文件损坏或缺失引起的&#xff0c;给计算机的正常运行带来了困扰。为了解决这个问题&#xff0c;我总结了以下五种方法&#xff…

深入解析 迭代器

前言 问&#xff1a;什么是迭代器 ? 答&#xff1a;在C# 中&#xff0c;迭代器是一种设计模式&#xff0c;它允许一个类或集合&#xff08;比如数组、列表或字典&#xff09;的实例提供一种遍历其元素的方式。在C#2时引入的迭代器&#xff0c;来简化这一过程。 在C#中有少…

【每天五道题,轻松公务员】Day2:世界地理

目录 专栏了解 ☞欢迎订阅☜ ★专栏亮点★ ◇专栏作者◇ 世界地理 题目一 题目二 题目三 题目四 题目五 答案 详细讲解 专栏了解 ☞欢迎订阅☜ 欢迎订阅此专栏&#xff1a;考公务员&#xff0c;必订&#xff01;https://blog.csdn.net/m0_73787047/category_1254…

顶帽运算在OpenCv中的应用

项目背景 假如我们拍了一张自拍&#xff0c;想为自己的照片添加一个酷炫的火星飞舞的效果&#xff0c;素材库中正好有一张火焰的照片&#xff0c;如果想去除图中的火焰&#xff0c;只保留火星效果&#xff0c;可以使用顶帽子算法 图片中的火星部分正好属于比周围亮一些的斑块…

LabVIEW开发滚筒洗衣机动态监测系统

LabVIEW软件在滚筒洗衣机的动态监测和分析中扮演着关键角色。本案例展示了如何利用LabVIEW开发的系统来优化洗衣机的性能和可靠性。 首先&#xff0c;在建立洗衣机的动力学模型基础上&#xff0c;利用LabVIEW进行了关键零部件的动态优化设计。通过LabVIEW的高级计算和模拟功能…

【JavaFX】JDK11 基于Gson、hutool、Jackson持久化存储实体类数据的解决方案 (读取、追加、去重、写入json对象)

文章目录 开发环境效果前言一、Gson是什么?二、使用步骤1.引入依赖2.创建实体类创建 JsonFileService类创建JsonFileService的实现类 JsonFileServiceImpl三、实现效果开发环境 JDK11IDEA 2023.3Gson、hutool、JacksonJavaFX 11效果 前言 使用JDK1

112. 雷达设备(贪心/逆向思考)

题目&#xff1a; 112. 雷达设备 - AcWing题库 输入样例&#xff1a; 3 2 1 2 -3 1 2 1输出样例&#xff1a; 2 思路&#xff1a; 代码&#xff1a; #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include<…

组件通信方式

组件通信方式有&#xff1a;vuex&#xff0c;ref&#xff0c;父子通信&#xff08;父传子、子传父&#xff09;&#xff0c;兄弟通信(eventBus)&#xff0c; 祖先后代通信&#xff08;依赖注入&#xff09; 父传子&#xff1a;父组件内&#xff1a;在子组件标签上设置自定义属…

BMS、AFE、菊花链技术

一、BMS的分布式架构和集中式架构 AFE在从板中&#xff0c;用来采集电池电压和温度&#xff0c;以及均衡管理 BMS通常以分布式架构为主&#xff0c;即分为主板和从板。原来主从板上都有微处控制器。从板采集单体电池电压和温度&#xff0c;通过CAN总线传给主板。 而现在的趋势…