从 0 开始讲透 C++ 并发(二):为什么需要 mutex?(数据竞争 + 解决方案)

发布时间:2026/5/19 10:59:02

从 0 开始讲透 C++ 并发(二):为什么需要 mutex?(数据竞争 + 解决方案) 承接上一篇C并发编程第一篇线程基础对标Java从0讲透 我们已经学会了✔ std::thread 创建线程✔ lambda 在线程中的使用✔ join / detach✔ 生命周期问题 但真正的并发问题其实刚刚开始一、问题多线程同时操作变量会发生什么示例#include iostream #include thread int main() { int a 0; std::thread t1([]{ for(int i 0; i 100000; i) { a; } }); std::thread t2([]{ for(int i 0; i 100000; i) { a; } }); t1.join(); t2.join(); std::cout a std::endl; }你以为 200000 ❌ 实际随机值 ❗比如 137842、189201…二、为什么会出错核心理解 关键点a 不是一个原子操作 实际执行过程1️⃣ 读取 a2️⃣ a 13️⃣ 写回 a 多线程同时执行线程1读 a 10线程2读 a 10线程1写 11线程2写 11 ❌覆盖 结果数据丢失 → 最终结果错误三、问题本质必须理解多个线程同时访问共享资源并且至少有一个在写 → 就会出问题 核心模型共享资源 并发写 数据竞争对应第一篇线程已经能跑 ✔但资源没有保护 ❌四、解决方案mutex互斥锁 思想非常简单同一时间只允许一个线程访问资源正确写法#include iostream #include thread #include mutex int main() { int a 0; std::mutex m; std::thread t1([]{ for(int i 0; i 100000; i) { std::lock_guardstd::mutex lock(m); a; } }); std::thread t2([]{ for(int i 0; i 100000; i) { std::lock_guardstd::mutex lock(m); a; } }); t1.join(); t2.join(); std::cout a std::endl; } 输出200000 ✔五、lock_guard 是什么重点std::lock_guardstd::mutex lock(m);含义构造时加锁作用域结束自动解锁本质RAII资源自动管理❌ 不推荐写法m.lock();a;m.unlock();问题中途异常 → unlock 不执行 → 死锁 ❗所以必须用lock_guard标准写法六、Java synchronized 对比理解帮助快速建立认知在理解mutex的时候如果你有 Java 背景可以这样对比Java 写法synchronized (obj) { a; }含义进入代码块 → 自动加锁退出代码块 → 自动释放锁C 写法std::mutex m; { std::lock_guardstd::mutex lock(m); a; }含义lock_guard 构造 → m.lock()lock_guard 析构 → m.unlock()解释 std::lock_guard 创建锁离开作用域释放锁。核心对比必须理解维度Java synchronizedC mutex控制方式语言级关键字库级类锁绑定代码块对象生命周期自动释放✔✔RAII使用方式简单更灵活七、临界区重要概念 临界区需要被保护的代码区域 示例{ std::lock_guardstd::mutex lock(m); a; // 临界区 }原则 临界区越小越好八、一个常见错误很多人会踩❌ 错误写法std::lock_guardstd::mutex lock(m); for(int i 0; i 100000; i) { a; } 问题锁范围太大 → 性能极差✅ 正确写法for(...) { std::lock_guardstd::mutex lock(m); a; }九、总结笔记版数据竞争Data Race 原因 多个线程同时访问共享变量至少一个写 问题 a 不是原子操作 → 数据错乱 解决 std::mutex lock_guard 核心 同一时间只允许一个线程访问 关键概念 临界区 被保护的代码 原则 锁范围越小越好 必须用 lock_guardRAII十、一句话总结mutex 的作用是保证共享资源在同一时间只能被一个线程访问从而避免数据竞争问题十一、你现在的进度非常关键你已经完成✔ 第1篇线程 lambda✔ 第2篇数据竞争 mutex 你已经进入C 并发核心阶段下一篇第3篇《C 并发三为什么需要 unique_lock比 lock_guard 更强大》

相关新闻