0

0

c++如何使用互斥锁mutex_c++多线程同步教程【示例】

穿越時空

穿越時空

发布时间:2026-01-29 15:04:02

|

318人浏览过

|

来源于php中文网

原创

必须用RAII管理std::mutex:优先std::lock_guard(简单场景)或std::unique_lock(需try_lock/condition_variable等),禁用手动lock/unlock;多锁须按固定顺序或用std::scoped_lock避免死锁;shared_mutex慎用于写频繁场景,且不可复制移动。

c++如何使用互斥锁mutex_c++多线程同步教程【示例】

std::mutex 必须配合 std::lock_guard 或 std::unique_lock 使用

直接调用 mutex.lock()mutex.unlock() 极易出错——比如异常抛出后忘记解锁,导致死锁。C++ 标准库不鼓励手动管理锁的生命周期。

正确做法是依赖 RAII:用 std::lock_guard作用域自动加锁/解锁)或 std::unique_lock(支持延迟锁定、转移所有权等高级操作)。

  • std::lock_guard 更轻量,适用于“进作用域就锁、出作用域就放”的简单场景
  • std::unique_lock 开销略大,但支持 try_lock()unlock() 手动释放、与 std::condition_variable 配合
  • 绝不要在同一个线程中对已持有的 std::mutex 再次调用 lock() ——这是未定义行为,不是可重入锁

多个 mutex 按固定顺序加锁,避免死锁

当一段逻辑需要同时持有两个或以上互斥锁时,如果线程 A 先锁 mtx1 再锁 mtx2,而线程 B 反过来先锁 mtx2 再锁 mtx1,就可能形成环形等待。

解决方法是全局约定加锁顺序(例如按地址大小、按变量声明顺序),或使用 std::scoped_lock(C++17 起)一次性按无序方式安全加锁:

立即学习C++免费学习笔记(深入)”;

std::mutex mtx1, mtx2;
// 安全:自动按内部顺序加锁,不会死锁
std::scoped_lock lock(mtx1, mtx2);
  • std::scoped_lockstd::lock_guard 的多锁升级版,构造即加锁,析构即解锁
  • 旧代码若用 std::lock(mtx1, mtx2) + std::lock_guard 手动构造,容易漏掉 adopt_lock 参数,导致重复加锁崩溃
  • 别用 std::try_lock 循环抢锁代替顺序约定——它只是绕开问题,不能根除竞争逻辑缺陷

shared_mutex 适合读多写少场景,但注意 writer starvation

std::shared_mutex(C++17)允许多个 reader 并发访问,writer 独占访问。但它不保证公平性:持续的 reader 请求可能让 writer 无限等待。

笔头写作
笔头写作

AI为论文写作赋能,协助你从0到1。

下载

如果你的场景写操作频率不低,或对写延迟敏感,std::shared_mutex 反而比普通 std::mutex 更慢、更难调试。

  • reader 使用 std::shared_lock<:shared_mutex>
  • writer 使用 std::unique_lock<:shared_mutex>
  • Windows 上对应的是 SRWLOCK,Linux glibc 实现早期有性能问题,建议用较新编译器(GCC 9+/Clang 8+)
  • 不要在持有 shared_lock 期间调用可能阻塞或抛异常的函数——否则 reader 长时间不释放,会拖垮 writer

std::mutex 不能跨线程复制或移动,只支持默认构造和销毁

std::mutex 是不可复制、不可移动的类型。试图把它放进 std::vector<:mutex> 或作为结构体成员被拷贝,编译直接报错:

error: use of deleted function 'std::mutex::mutex(const std::mutex&)'

常见误用包括:

  • std::mutex 当作普通成员变量,在类赋值运算符中没显式忽略它
  • 想用 std::make_shared() 创建含 mutex 的对象,却忘了 MyClass 的构造函数必须显式初始化 mutex(默认构造即可)
  • 在线程函数里传入局部 std::mutex 的引用——该 mutex 随函数返回被销毁,其他线程再访问就是 dangling reference

真正需要“多个锁”时,应静态分配、全局唯一,或用指针/智能指针管理生命周期,而不是尝试复制锁本身。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1501

2023.10.24

Go语言中的运算符有哪些
Go语言中的运算符有哪些

Go语言中的运算符有:1、加法运算符;2、减法运算符;3、乘法运算符;4、除法运算符;5、取余运算符;6、比较运算符;7、位运算符;8、按位与运算符;9、按位或运算符;10、按位异或运算符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

232

2024.02.23

php三元运算符用法
php三元运算符用法

本专题整合了php三元运算符相关教程,阅读专题下面的文章了解更多详细内容。

87

2025.10.17

golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

220

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

192

2025.07.04

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

503

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

166

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

14

2026.01.21

clawdbot ai使用教程 保姆级clawdbot部署安装手册
clawdbot ai使用教程 保姆级clawdbot部署安装手册

Clawdbot是一个“有灵魂”的AI助手,可以帮用户清空收件箱、发送电子邮件、管理日历、办理航班值机等等,并且可以接入用户常用的任何聊天APP,所有的操作均可通过WhatsApp、Telegram等平台完成,用户只需通过对话,就能操控设备自动执行各类任务。

19

2026.01.29

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 8万人学习

Git 教程
Git 教程

共21课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号