0

0

C++中的并发与锁怎么用?C++ mutex互斥锁使用教程【多线程安全】

裘德小鎮的故事

裘德小鎮的故事

发布时间:2025-12-14 02:25:24

|

267人浏览过

|

来源于php中文网

原创

多线程中需用std::mutex等同步机制保证共享数据访问安全,核心是所有读写均须在持锁下进行;推荐RAII方式如std::lock_guard或std::unique_lock管理锁,避免手动lock/unlock出错;注意mutable修饰互斥量以支持const函数加锁,多锁场景优先用std::scoped_lock防死锁。

c++中的并发与锁怎么用?c++ mutex互斥锁使用教程【多线程安全】

多线程环境下,多个线程同时访问共享数据容易引发数据竞争(data race),导致结果不可预测。C++ 提供 std::mutex同步机制来保证线程安全,核心原则是:**任何对共享资源的读写,都必须在持有互斥锁的前提下进行**。

mutex 基本用法:加锁、解锁、RAII 自动管理

手动调用 lock()unlock() 容易出错(比如忘记解锁、异常跳过解锁)。推荐使用 RAII 封装类:std::lock_guard作用域内自动加锁/解锁)或更灵活的 std::unique_lock

  • std::lock_guard<:mutex> guard(mtx); —— 构造时加锁,离开作用域自动解锁(不能转移、不可复制)
  • std::unique_lock<:mutex> lock(mtx); —— 支持延迟加锁、手动解锁、条件变量配合等
  • 不要手动调用 mtx.unlock() 配合 lock_guard,否则会触发未定义行为

保护共享变量:典型线程安全计数器示例

下面是一个带锁的线程安全计数器:

class ThreadSafeCounter {
    mutable std::mutex mtx;
    int value = 0;
public:
    void increment() {
        std::lock_guard lock(mtx);
        ++value;
    }
    int get() const {
        std::lock_guard lock(mtx);
        return value;
    }
};

注意:mutable 允许在 const 成员函数中修改互斥量(因为锁操作不改变逻辑状态);get()const 函数,但内部仍需加锁读取共享值。

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

VWO
VWO

一个A/B测试工具

下载

避免死锁:按固定顺序加锁 & 使用 std::scoped_lock

多个互斥量同时使用时,若线程 A 锁 mtx1 再锁 mtx2,而线程 B 反过来先锁 mtx2 再锁 mtx1,就可能死锁。

  • 一加锁顺序(如地址大小、ID 编号)——需人工约定,易出错
  • 更推荐:用 std::scoped_lock(C++17 起),可安全同时锁定多个互斥量,自动避免死锁
  • 示例:std::scoped_lock lock(mtx1, mtx2); —— 内部按无死锁策略加锁,构造成功才全部持有

常见误区与注意事项

实际开发中容易踩坑的地方:

  • 只保护写操作,忽略读操作——读操作同样需要锁(除非用原子类型或读写锁)
  • 锁粒度太大(如整个函数都持锁)→ 性能差;太小(如每行都加锁)→ 逻辑错误或漏锁
  • 在持有锁时调用未知外部函数(如用户回调、IO、new/delete)——可能阻塞或抛异常,延长持锁时间甚至引发死锁
  • std::mutex 不可拷贝、不可移动,只能通过引用或指针共享;多个线程应共用同一个 mutex 实例

基本上就这些。用好 mutex 的关键是:明确共享数据边界、最小化临界区、优先用 RAII、警惕死锁和异常路径。不复杂但容易忽略细节。

相关专题

更多
c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

526

2023.09.20

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

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

482

2023.08.10

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

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

143

2025.12.24

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

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

5

2026.01.21

C++多线程相关合集
C++多线程相关合集

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

5

2026.01.21

数据库Delete用法
数据库Delete用法

数据库Delete用法:1、删除单条记录;2、删除多条记录;3、删除所有记录;4、删除特定条件的记录。更多关于数据库Delete的内容,大家可以访问下面的文章。

269

2023.11.13

drop和delete的区别
drop和delete的区别

drop和delete的区别:1、功能与用途;2、操作对象;3、可逆性;4、空间释放;5、执行速度与效率;6、与其他命令的交互;7、影响的持久性;8、语法和执行;9、触发器与约束;10、事务处理。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

210

2023.12.29

Java编译相关教程合集
Java编译相关教程合集

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

9

2026.01.21

C++多线程相关合集
C++多线程相关合集

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

3

2026.01.21

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

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

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