C++多线程编程中的锁详解
在现代软件开发中,多线程编程是提升应用程序性能和响应能力的重要手段。然而,多线程编程也带来了数据竞争和死锁等复杂问题。为了确保线程间的同步和共享数据的一致性,C++标准库提供了多种锁机制。
1. std::mutex
std::mutex是最基础的互斥锁,用于保护共享数据,防止多个线程同时访问该数据。
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;void print_thread_id(int id) {mtx.lock();std::cout << "Thread " << id << std::endl;mtx.unlock();
}int main() {std::thread t1(print_thread_id, 1);std::thread t2(print_thread_id, 2);t1.join();t2.join();return 0;
}
在上述代码中,mtx.lock()和mtx.unlock()分别用于加锁和解锁,确保同一时刻只有一个线程可以访问临界区(std::cout操作)。
2. std::recursive_mutex
std::recursive_mutex允许同一线程多次获得同一锁,而不会导致死锁。适用于递归调用中需要加锁的场景。
#include <iostream>
#include <thread>
#include <mutex>std::recursive_mutex rec_mtx;void recursive_function(int count) {if (count <= 0) return;rec_mtx.lock();std::cout << "Count: " << count << std::endl;recursive_function(count - 1);rec_mtx.unlock();
}int main() {std::thread t(recursive_function, 5);t.join();return 0;
}
3. std::timed_mutex
std::timed_mutex支持尝试在一定时间内获取锁。这在避免死锁和提高程序响应性方面很有用。
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>std::timed_mutex tmtx;void try_lock_for_example() {if (tmtx.try_lock_for(std::chrono::seconds(1))) {std::cout << "Lock acquired" << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));tmtx.unlock();} else {std::cout << "Failed to acquire lock" << std::endl;}
}int main() {std::thread t1(try_lock_for_example);std::thread t2(try_lock_for_example);t1.join();t2.join();return 0;
}
4. std::recursive_timed_mutex
std::recursive_timed_mutex结合了std::recursive_mutex和std::timed_mutex的特性
#include <iostream>
#include <thread>
#include <mutex>
#include <chrono>std::recursive_timed_mutex rtmtx;void recursive_timed_function(int count) {if (count <= 0) return;if (rtmtx.try_lock_for(std::chrono::seconds(1))) {std::cout << "Count: " << count << std::endl;recursive_timed_function(count - 1);rtmtx.unlock();} else {std::cout << "Failed to acquire lock" << std::endl;}
}int main() {std::thread t(recursive_timed_function, 5);t.join();return 0;
}
5. std::shared_mutex(C++17引入)
std::shared_mutex允许多个线程同时读取共享数据,但只允许一个线程写入数据。这种机制适用于读多写少的场景。
#include <iostream>
#include <thread>
#include <shared_mutex>std::shared_mutex smtx;void read_function() {smtx.lock_shared();std::cout << "Reading data" << std::endl;smtx.unlock_shared();
}void write_function() {smtx.lock();std::cout << "Writing data" << std::endl;smtx.unlock();
}int main() {std::thread t1(read_function);std::thread t2(read_function);std::thread t3(write_function);t1.join();t2.join();t3.join();return 0;
}
6. std::shared_timed_mutex(C++14引入)
std::shared_timed_mutex结合了std::shared_mutex和std::timed_mutex的特性。
#include <iostream>
#include <thread>
#include <shared_mutex>
#include <chrono>std::shared_timed_mutex stmtx;void shared_timed_read_function() {if (stmtx.try_lock_shared_for(std::chrono::seconds(1))) {std::cout << "Reading data" << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));stmtx.unlock_shared();} else {std::cout << "Failed to acquire shared lock" << std::endl;}
}void shared_timed_write_function() {if (stmtx.try_lock_for(std::chrono::seconds(1))) {std::cout << "Writing data" << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));stmtx.unlock();} else {std::cout << "Failed to acquire exclusive lock" << std::endl;}
}int main() {std::thread t1(shared_timed_read_function);std::thread t2(shared_timed_read_function);std::thread t3(shared_timed_write_function);t1.join();t2.join();t3.join();return 0;
}
7. std::lock_guard
std::lock_guard提供一种异常安全的方式来管理锁的生命周期,通常用于自动解锁。
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;void lock_guard_example() {std::lock_guard<std::mutex> lock(mtx);std::cout << "Lock acquired using lock_guard" << std::endl;// mtx is automatically unlocked when lock goes out of scope
}int main() {std::thread t(lock_guard_example);t.join();return 0;
}
8. std::unique_lock
std::unique_lock比std::lock_guard更加灵活,支持延迟加锁、解锁和重新加锁。
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx;void unique_lock_example() {std::unique_lock<std::mutex> lock(mtx);std::cout << "Lock acquired using unique_lock" << std::endl;lock.unlock();std::cout << "Lock released" << std::endl;lock.lock();std::cout << "Lock reacquired" << std::endl;
}int main() {std::thread t(unique_lock_example);t.join();return 0;
}
9. std::shared_lock(C++17引入)
std::shared_lock用于管理共享互斥量(std::shared_mutex或std::shared_timed_mutex),提供了一种简单的方式来处理读锁。
#include <iostream>
#include <thread>
#include <shared_mutex>std::shared_mutex smtx;void shared_lock_example() {std::shared_lock<std::shared_mutex> lock(smtx);std::cout << "Shared lock acquired" << std::endl;
}int main() {std::thread t1(shared_lock_example);std::thread t2(shared_lock_example);t1.join();t2.join();return 0;
}
结论
C++标准库提供了多种锁机制,帮助开发者在多线程环境中确保数据的一致性和线程的同步。根据具体的应用场景选择合适的锁,可以有效地避免数据竞争和死锁问题,从而编写出高效、安全的多线程程序。
相关文章:
C++多线程编程中的锁详解
在现代软件开发中,多线程编程是提升应用程序性能和响应能力的重要手段。然而,多线程编程也带来了数据竞争和死锁等复杂问题。为了确保线程间的同步和共享数据的一致性,C标准库提供了多种锁机制。 1. std::mutex std::mutex是最基础的互斥锁…...
van-dialog 组件调用报错
报错截图 报错原因 这个警告表明 vue 在渲染页面时遇到了一个未知的自定义组件 <van-dialog>,并且提示可能是由于未正确注册该组件导致的。在 vue 中,当我们使用自定义组件时,需要先在 vue 实例中注册这些组件,以便 vue 能…...
【Django】在vscode中运行调试Django项目(命令及图形方式)
文章目录 命令方式图形方式默认8000端口设置自定义端口 命令方式 python manage.py runserver图形方式 默认8000端口 设置自定义端口...
麦田物语第十三天
系列文章目录 麦田物语第十三天 文章目录 系列文章目录一、实现根据物品详情显示 ItemTooltip1.ItemTooltips脚本编写二、制作 Player 的动画一、实现根据物品详情显示 ItemTooltip 1.ItemTooltips脚本编写 首先创建Scripts->Inventory->UI->ItemTooltip脚本,然后…...
【Git多人协作开发】不同的分支下的多人协作开发模式
目录 0.前言背景 1.开发者1☞完成准备工作&协作开发 1.1查看分支情况 1.2创建本地分支feature-1 1.3三板斧 1.4push推本地分支feature-1到远程仓库 2.开发者2☞完成准备工作&协作开发 2.1创建本地分支feature-2 2.2三板斧 2.2push推送本地feature-2到远程仓库…...
Lua 复数计算器
Lua复数计算器 主要包括复数的加减乘除操作,以及打印 编写复数类 -- ***** 元类 ***** Complex {real 0, imag 0}-- 构造函数 function Complex:new(real, imag)local o o or {}o.real real or 0o.imag imag or 0setmetatable(o, self)self.__index selfr…...
深入MySQL中的IF和IFNULL函数
在数据库查询中,我们经常需要根据条件来决定数据的显示方式。MySQL提供了多种内置函数来帮助我们实现这种条件逻辑,其中IF和IFNULL是两个非常有用的函数。在这篇博客中,我们将深入探讨这两个函数的用法和它们在实际查询中的应用。 IF函数 I…...
AI多模态实战教程:面壁智能MiniCPM-V多模态大模型问答交互、llama.cpp模型量化和推理
一、项目简介 MiniCPM-V 系列是专为视觉-语⾔理解设计的多模态⼤型语⾔模型(MLLMs),提供⾼质量的⽂本输出,已发布4个版本。 1.1 主要模型及特性 (1)MiniCPM-Llama3-V 2.5: 参数规模: 8B性能…...
Docker 搭建Elasticsearch详细步骤
本章教程使用Docker搭建Elasticsearch环境。 一、拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.8.2二、运行容器 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-n...
mysql中提供的函数
文章目录 1.聚合函数2.字符串函数3.数值函数4.日期函数5.流程函数 MySQL 是一个功能强大的关系型数据库管理系统,其中包含了丰富的内置函数,用于处理各种数据操作和查询。这些函数可以分为多种类型,包括字符串函数、数值函数、日期和时间函数…...
加速下载,揭秘Internet Download Manager2024下载器的威力!
1. Internet Download Manager(IDM)是一款广受欢迎的下载管理软件,以其强大的下载加速功能和用户友好的界面著称。 IDM马丁正版下载如下: https://wm.makeding.com/iclk/?zoneid34275 idm最新绿色版一键安装包链接:抓紧保存以…...
oracle 宽表设计
Oracle宽表设计主要涉及到数据库表或视图中字段(列)数量较多的情况。在Oracle 23c及以后的版本中,数据库表或视图中允许的最大列数已增加到4096,这为宽表设计提供了更大的灵活性。以下是对Oracle宽表设计的详细分析: …...
winrar安装好后,鼠标右键没有弹出解压的选项
本来安装挺好的,可以正常使用,有天我把winrar相关的文件挪了个位置,就不能正常使用了。 然后我去应用里面找,找到应用标识了,但是找不到对应的文件夹(因为我挪到另外一个文件夹里了)。 于是我找…...
数字图像处理笔记(一)---- 图像数字化与显示
系列文章目录 数字图像处理学习笔记(一)---- 图像数字化与显示 数字图像处理笔记(二)---- 像素加图像统计特征 数字图像处理笔记(三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、数字图像处理二、图像数…...
Unity UGUI 之 事件接口
本文仅作学习笔记与交流,不作任何商业用途 本文包括但不限于unity官方手册,唐老狮,麦扣教程知识,引用会标记,如有不足还请斧正 本文在发布时间选用unity 2022.3.8稳定版本,请注意分别 1.什么是事件接口&…...
Hadoop、HDFS、MapReduce 大数据解决方案
本心、输入输出、结果 文章目录 Hadoop、HDFS、MapReduce 大数据解决方案前言HadoopHadoop 主要组件的Web UI端口和一些基本信息MapReduceMapReduce的核心思想MapReduce的工作流程MapReduce的优缺点Hadoop、HDFS、MapReduce 大数据解决方案 编辑 | 简简单单 Online zuozuo 地址…...
Dubbo SPI 之负载均衡
1. 背景介绍 在分布式系统中,负载均衡是一项核心技术,旨在将请求合理地分配到多个服务实例上,以提高系统的性能和可靠性。Dubbo 作为一个高性能的 Java RPC 框架,提供了多种负载均衡策略来满足不同的业务需求。本文将深入探讨 Du…...
规范:前后端接口规范
1、前言 随着互联网的高速发展,前端页面的展示、交互体验越来越灵活、炫丽,响应体验也要求越来越高,后端服务的高并发、高可用、高性能、高扩展等特性的要求也愈加苛刻,从而导致前后端研发各自专注于自己擅长的领域深耕细作。 然…...
Python --NumPy库基础方法(2)
NumPy Numpy(Numerical Python) 是科学计算基础库,提供大量科学计算相关功能,比如数据统计,随机数生成等。其提供最核心类型为多维数组类型(ndarray),支持大量的维度数组与矩阵运算,Numpy支持向…...
音视频入门基础:H.264专题(15)——FFmpeg源码中通过SPS属性获取视频帧率的实现
音视频入门基础:H.264专题系列文章: 音视频入门基础:H.264专题(1)——H.264官方文档下载 音视频入门基础:H.264专题(2)——使用FFmpeg命令生成H.264裸流文件 音视频入门基础&…...
Godot引擎集成CEF实现Web混合渲染:gdcef项目架构与实战指南
1. 项目概述与核心价值最近在折腾一个老项目的现代化改造,需要把传统的桌面应用嵌入到Web视图中,实现混合渲染。在技术选型时,我绕不开一个名字:CEF,也就是Chromium Embedded Framework。它几乎是桌面应用内嵌浏览器控…...
PhonePi-MCP:基于MCP协议实现AI智能体自动化操控Android手机
1. 项目概述:当你的手机成为AI的“眼睛”与“双手” 最近在折腾AI智能体(Agent)时,我一直在思考一个问题:如何让这些运行在云端或本地电脑上的“大脑”真正地与现实世界互动?比如,让它帮我查一…...
“梦想、汗水、坚持”2026 SNH48 GROUP年度青春盛典5月30日正式启动
“十三而砺,向新而行。”中国大型青春女团SNH48 GROUP运营方上海丝芭文化传媒集团有限公司即日宣布:2026 SNH48 GROUP第十三届年度青春盛典大型系列活动将于5月30日正式启动,本届年度青春盛典颁奖典礼暨汇报演唱会定档8月8日,落地…...
AI技能库实战:模块化设计赋能博客创作自动化工作流
1. 项目概述:一个面向AI时代的博客技能开源库最近在GitHub上闲逛,发现了一个挺有意思的项目,叫inblog-inc/inblog-ai-skills。光看这个名字,就透着一股子“务实”的味道。它不是又一个教你如何调参炼丹的AI模型库,也不…...
终极指南:3分钟掌握Mouse Jiggler鼠标模拟器完整使用方法
终极指南:3分钟掌握Mouse Jiggler鼠标模拟器完整使用方法 【免费下载链接】mousejiggler Mouse Jiggler is a very simple piece of software whose sole function is to "fake" mouse input to Windows, and jiggle the mouse pointer back and forth. …...
MySQL数据库基础3--(函数)完
一、聚合函数聚合函数包括COUNT()、SUM()、AVG()、MAX()和MIN()。当需要对表中的记录求和、求平均值、查询最大值和查询最小值等操作时,可以使用聚合函数。GROUP BY关键字通常需要与聚合函数一起使用。COUNT()用来统计记录的条数;SUM()用来计算字段的值的…...
对话式AI智能中继与编排框架:构建高可用AI应用的核心架构
1. 项目概述:一个面向对话式AI的智能中继与编排框架最近在折腾一个挺有意思的开源项目,叫ChatAgentRelay。乍一看这个名字,可能觉得它又是一个聊天机器人框架,但深入把玩之后,我发现它的定位其实更精准,也更…...
168.YOLOv8零基础直达实战|COCO128+CU118环境+完整注释代码
摘要 YOLO(You Only Look Once)系列算法是目标检测领域最主流的实时检测框架,从v1到v8经历了多次架构迭代与性能飞跃。本文旨在提供一份零基础直达实战的完整指南,不依赖任何图片,仅通过逻辑推导与代码实现,帮助读者掌握YOLO的核心原理、环境搭建、模型训练、推理部署及…...
明日方舟素材库:从游戏资产到创意引擎的技术解密
明日方舟素材库:从游戏资产到创意引擎的技术解密 【免费下载链接】ArknightsGameResource 明日方舟客户端素材 项目地址: https://gitcode.com/gh_mirrors/ar/ArknightsGameResource 在数字创作的广阔天地中,专业级游戏素材往往被锁在商业游戏的围…...
明日方舟游戏资源库:2000+高清素材的完整获取与应用指南
明日方舟游戏资源库:2000高清素材的完整获取与应用指南 【免费下载链接】ArknightsGameResource 明日方舟客户端素材 项目地址: https://gitcode.com/gh_mirrors/ar/ArknightsGameResource 还在为寻找高质量的明日方舟游戏素材而烦恼吗?无论是创作…...
