当前位置: 首页 > news >正文

【C++】详解std::mutex

2023年9月11日,周一中午开始

2023年9月11日,周一晚上23:25写完


目录

  • 概述
  • 头文件
  • std::mutex类的成员
  • 类型
  • 方法
  • 没有std::mutex会产生什么问题
  • 问题一:数据竞争
  • 问题二:不一致
  • lock和unlock
  • 死锁

概述

std::mutex是C++标准库中提供的一种同步原语,用于保护共享资源的访问

std::mutex通过锁定互斥锁来实现对共享资源的保护。当一个线程获取了互斥锁后,其他线程必须等待该互斥锁被释放才能继续访问共享资源。这样可以确保在同一时刻只有一个线程能够访问共享资源,从而避免了多个线程同时访问同一资源而导致的数据竞争不一致问题。

头文件

#include<mutex>

std::mutex类的成员

类型

native_handle_type    原生的互斥锁句柄类型

方法

(constructor)    构造互斥锁(公共函数)

lock    锁上互斥锁(公共函数)

try_lock    如果互斥锁没锁上就锁上互斥锁(公共函数)

unlock    解除互斥锁(公共函数)

native_handle    获取原生的互斥锁句柄(公共函数)

没有std::mutex会产生什么问题

问题一:数据竞争

在这个程序中,共享资源是count,count的值为0

按理来说,一个线程给count增加100000,另一个线程给count减去100000,最后的count应该还是0,但是事实上却不是这样,这就是数据竞争所造成的。

#include <iostream>
#include <mutex>
#include <thread>int count = 0;void thread1() {for(int i = 0; i < 100000; i++) {count++; }
}void thread2() {for(int i = 0; i < 100000; i++) {  count--;}
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();std::cout <<"count:"<< count << std::endl; // 可能打印非0值
}

问题二:不一致

多个线程对共享数据进行操作,由于缓存一致性问题,可能导致其中一个线程看到的数据不是最新值。

比如在这个程序里面,有时候判断x==1是true,有时候判断x==1是false

#include <iostream>
#include <mutex>
#include <thread>int x = 0;void thread1() {x = 1; 
}void thread2() {if(x == 1)std::cout << "x is 1" << std::endl; elsestd::cout << "x is not 1" << std::endl; 
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();}

lock和unlock

通过lock/unlock可以保证任何时刻只有一个线程在访问共享资源,从而避免数据竞争问题。

#include <iostream>
#include <mutex>
#include <thread>std::mutex mutex;
int count = 0;void thread1() {for(int i = 0; i < 100000; i++) {// 锁定互斥锁mutex.lock();  count++; // 解锁互斥锁mutex.unlock();}
}void thread2() {for(int i = 0; i < 100000; i++) {  // 锁定互斥锁mutex.lock();  count--;// 解锁互斥锁mutex.unlock();}
}int main() {std::thread t1(thread1);std::thread t2(thread2);t1.join();t2.join();std::cout <<"count:"<< count << std::endl; 
}

可以看到数据竞争的问题得到了解决

死锁

死锁(Deadlock)是多线程或多进程编程中的一个严重问题,它会导致程序无法继续执行下去,因为一组线程或进程相互等待对方释放资源,但永远无法满足条件,从而陷入僵局。

死锁的定义是:多个线程因为抢占和持有资源而造成的一种互相等待的僵局状态

#include <iostream>
#include <thread>
#include <mutex>std::mutex mutex1;
std::mutex mutex2;void threadA() {std::cout << "Thread A: Attempting to lock mutex1..." << std::endl;mutex1.lock();std::this_thread::sleep_for(std::chrono::milliseconds(1));std::cout << "Thread A: Attempting to lock mutex2..." << std::endl;mutex2.lock();// 执行任务...mutex2.unlock();mutex1.unlock();
}void threadB() {std::cout << "Thread B: Attempting to lock mutex2..." << std::endl;mutex2.lock();std::this_thread::sleep_for(std::chrono::milliseconds(1));std::cout << "Thread B: Attempting to lock mutex1..." << std::endl;mutex1.lock();// 执行任务...mutex1.unlock();mutex2.unlock();
}int main() {std::thread t1(threadA);std::thread t2(threadB);t1.join();t2.join();return 0;
}

可以看到程序一直卡住

为什么会卡住呢?

  1. 线程A首先尝试锁定mutex1,并成功获得锁。

  2. 线程B首先尝试锁定mutex2,并成功获得锁。

  3. 接下来,线程A想要锁定mutex2,但它被线程B持有,因此线程A被阻塞,无法继续执行,等待mutex2被释放。

  4. 同样地,线程B想要锁定mutex1,但它被线程A持有,因此线程B也被阻塞,等待mutex1被释放。

现在,线程A和线程B都被阻塞,它们相互等待对方释放资源,但又不会主动释放自己的锁。这就是典型的死锁情况:两个或多个线程互相等待对方释放资源,导致程序无法继续执行下去。

根本原因在于线程拿不到锁时就会被阻塞。

相关文章:

【C++】详解std::mutex

2023年9月11日&#xff0c;周一中午开始 2023年9月11日&#xff0c;周一晚上23&#xff1a;25写完 目录 概述头文件std::mutex类的成员类型方法没有std::mutex会产生什么问题问题一&#xff1a;数据竞争问题二&#xff1a;不一致lock和unlock死锁 概述 std::mutex是C标准库中…...

Matlab图像处理-Lab模型

Lab模型 Lab模型是由CIE&#xff08;国际照明委员会&#xff09;制定的一种彩色模型。该模型与设备无关&#xff0c;弥补了RGB模型和CMYK模型必须依赖于设备颜色特性的不足&#xff1b; 另外&#xff0c;自然界中的任何颜色都可以在Lab空间中表现出来&#xff0c;也就是说RGB和…...

分布式ETL工具Sqoop实践

Mysql数据准备 1、在node02节点登录Mysql。 mysql -uroot -proot2、新建数据库testdb。 create database testdb;3、新建数据表ts。 use testdb; create table ts(id int, name varchar(10), age int, sex char(1));4、向表中插入数据。 insert into ts values(10001,张三…...

展会预告 | 图扑邀您共聚 IOTE 国际物联网展·深圳站

参展时间&#xff1a;9 月 20 日- 22 日 图扑展位&#xff1a;9 号馆 9B 35-1 参展地址&#xff1a;深圳国际会展中心&#xff08;宝安新馆&#xff09; IOTE 2023 第二十届国际物联网展深圳站&#xff0c;将于 9 月 20 日- 22 日在深圳国际会展中心&#xff08;宝安&#xf…...

如何下载安装 WampServer 并结合 cpolar 内网穿透,轻松实现对本地服务的公网访问

文章目录 前言1.WampServer下载安装2.WampServer启动3.安装cpolar内网穿透3.1 注册账号3.2 下载cpolar客户端3.3 登录cpolar web ui管理界面3.4 创建公网地址 4.固定公网地址访问 前言 Wamp 是一个 Windows系统下的 Apache PHP Mysql 集成安装环境&#xff0c;是一组常用来…...

iOS添加Mapbox地图库

配置凭据 注册并导航到Account页面。你将需要&#xff1a; 公共访问令牌&#xff1a; 从帐户的tokens页面&#xff0c;你可以复制默认的公共令牌或单击"create a token"按钮来创建新的公共令牌。 带有Downloads:Read范围的秘密访问令牌&#xff1a; 从你帐户的t…...

destoon根据目录下的html文件生成地图索引

因为项目需要&#xff0c;destoon根据目录下的html文件生成地图索引&#xff0c;操作方法&#xff0c;代码如下&#xff1a; <?php $new_array array(); function loopDir($dir,&$new_array,$modurl) {$handle opendir($dir);header("Content-Type:text/xml&qu…...

gRPC之gRPC流

1、gRPC流 从其名称可以理解&#xff0c;流就是持续不断的传输。有一些业务场景请求或者响应的数据量比较大&#xff0c;不适合使用普通的 RPC 调用通过一次请求-响应处理&#xff0c;一方面是考虑数据量大对请求响应时间的影响&#xff0c;另一方面业务场景的设计不一 定需…...

Kafka Shell命令交互

Kafka提供了一个命令行工具,用于管理和与Kafka集群交互。这个命令行工具通常称为Kafka Shell,它允许您执行各种操作,如创建主题、发送和消费消息、查看主题列表等。 以下是一些常用的Kafka Shell命令: 创建主题(Topic): kafka-topics.sh --create --topic my-topic --pa…...

什么是回归测试?

什么是回归测试&#xff1f; 回归测试被定义为一种软件测试类型&#xff0c;以确认最近的程序或代码更改未对现有功能产生不利影响。 回归测试只不过是全部或部分选择已执行的测试用例&#xff0c;然后重新执行以确保现有功能正常运行。 进行此测试是为了确保新代码更改不会…...

ZTMap是如何在相关政策引导下让建筑更加智慧化的?

近几年随着智慧楼宇概念的深入&#xff0c;尤其是在“十四五规划”“新基建”“数字经济”等相关战略和政策的引导下&#xff0c;智慧楼宇也迎来了快速发展期&#xff0c;对推动智慧城市系统的建设越来越重要。那么究竟什么是智慧楼宇呢&#xff1f;智慧楼宇其实就是整合楼宇内…...

Python:函数和代码复用

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 &#x1f447; &#x1f447; &#x1f447; 更多精彩机密、教程&#xff0c;尽在下方&#xff0c;赶紧点击了解吧~ python源码、视频教程、插件安装教程、资料我都准备好了&#xff0c;直接在文末名片自取就可 1、关于递归函…...

three.js——模型对象的使用材质和方法

模型对象的使用材质和方法 前言效果图1、旋转、缩放、平移&#xff0c;居中的使用1.1 旋转rotation&#xff08;.rotateX()、.rotateY()、.rotateZ()&#xff09;1.2缩放.scale()1.3平移.translate()1.4居中.center() 2、材质属性.wireframe 前言 BufferGeometry通过.scale()、…...

sql explain

目录 1. sql explain每个字段对应的含义1.1. id1.2. select_type1.3. table1.4. partitions1.5. type1.6. possible_keys1.7. key1.8. key_len1.9. ref1.10. rows1.11. Extra 索引实践联合索引最左列原则全值匹配不建议在索引列上做任何操作, 否则索引会失效转而全表扫描尽量使…...

【LeetCode-简单题】剑指 Offer 05. 替换空格

文章目录 题目方法一&#xff1a;常规做法&#xff1a;方法二&#xff1a;双指针做法 题目 方法一&#xff1a;常规做法&#xff1a; class Solution {public String replaceSpace(String s) {int len s.length() ;StringBuffer str new StringBuffer();for(int i 0 ; i &l…...

数字虚拟人制作简明指南

如何在线创建虚拟人&#xff1f; 虚拟人&#xff0c;也称为数字化身、虚拟助理或虚拟代理&#xff0c;是一种可以通过各种在线平台与用户进行逼真交互的人工智能人。 在线创建虚拟人变得越来越流行&#xff0c;因为它为个人和企业带来了许多好处。 推荐&#xff1a;用 NSDT编辑…...

Nginx 文件解析漏洞复现

一、漏洞说明 Nginx文件解析漏洞算是一个比较经典的漏洞&#xff0c;接下来我们就通过如下步骤进行漏洞复现&#xff0c;以及进行漏洞的修复。 版本条件&#xff1a;IIS 7.0/IIS 7.5/ Nginx <8.03 二、搭建环境 cd /vulhub/nginx/nginx_parsing_vulnerability docker-compos…...

Lombok依赖

一.介绍 Project Lombok 是一个 Java 库&#xff0c;它会自动插入编辑器和构建工具&#xff0c;为您的 Java 增添趣味。永远不要再写另一个 getter 或 equals 方法&#xff0c;使用一个注释&#xff0c;您的类有一个功能齐全的构建器&#xff0c;自动化您的日志记录变量等等。…...

XML 和 JSON 学习笔记(基础)

XML Why XML 的出现背景&#xff1a;在实际开发中&#xff0c;不同语言&#xff08;如Java、JavaScript等&#xff09;的应用程序之间数据传递的格式不同&#xff0c;导致它们进行数据交换时很困难&#xff0c;XML就应运而生了&#xff01;&#xff08;XML 是一种通用的数据交…...

L1-005 考试座位号分数 15

每个 PAT 考生在参加考试时都会被分配两个座位号&#xff0c;一个是试机座位&#xff0c;一个是考试座位。正常情况下&#xff0c;考生在入场时先得到试机座位号码&#xff0c;入座进入试机状态后&#xff0c;系统会显示该考生的考试座位号码&#xff0c;考试时考生需要换到考试…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

springboot 百货中心供应链管理系统小程序

一、前言 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;百货中心供应链管理系统被用户普遍使用&#xff0c;为方…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:

在 HarmonyOS 应用开发中&#xff0c;手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力&#xff0c;既支持点击、长按、拖拽等基础单一手势的精细控制&#xff0c;也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档&#xff0c…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Unsafe Fileupload篇补充-木马的详细教程与木马分享(中国蚁剑方式)

在之前的皮卡丘靶场第九期Unsafe Fileupload篇中我们学习了木马的原理并且学了一个简单的木马文件 本期内容是为了更好的为大家解释木马&#xff08;服务器方面的&#xff09;的原理&#xff0c;连接&#xff0c;以及各种木马及连接工具的分享 文件木马&#xff1a;https://w…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...