C++ 多线程与并发系统取向(二)—— 资源保护:std::mutex 与 RAII(类比 Java synchronized)

一、先问一个工程问题

你有一个共享容器:

std::vector<int> data;

两个线程同时往里面 push_back()

会发生什么?

你可能会说:

vector 不是自动扩容的吗?

是的,但:

vector 不是线程安全的。

内部会:

  • 修改 size
  • 可能 realloc
  • 移动内存

如果两个线程同时写:

未定义行为。

二、资源保护的本质

并发系统里最重要一句话:

不是“给代码加锁”,而是“给资源加保护策略”。

资源 = 被多个线程共享的数据。

三、什么是临界区(Critical Section)

临界区是:

访问共享资源的代码区域。

例如:

data.push_back(1);

这一行,就是临界区。

四、最原始写法(危险)

std::mutex mtx; void task() { mtx.lock(); data.push_back(1); mtx.unlock(); }

看起来没问题。

但如果中间抛异常?

mtx.lock(); throw std::runtime_error("error"); mtx.unlock(); // 永远执行不到

锁永远不释放。

其他线程:

永久阻塞(死锁)。

五、C++ 的核心思想:RAII

RAII = Resource Acquisition Is Initialization

意思:

资源的获取与对象生命周期绑定。

锁对象在构造时加锁,在析构时自动解锁。

这就是:

std::lock_guard

六、正确写法:std::lock_guard

std::mutex mtx; void task() { std::lock_guard<std::mutex> lock(mtx); data.push_back(1); }

作用:

  • 构造 → 自动 lock
  • 离开作用域 → 自动 unlock

无论:

  • return
  • 异常
  • break

都会释放锁。

七、Java 对比:synchronized

Java 写法:

synchronized (lock) { data.add(1); }

本质类似:

  • 进入代码块 → 加锁
  • 离开代码块 → 自动释放

区别:

C++Java
lock_guard 是对象synchronized 是语言关键字
手动控制 mutexJVM 管理 monitor

八、完整并发示例(安全版)

#include <iostream> #include <thread> #include <vector> #include <mutex> std::vector<int> data; std::mutex mtx; void task() { for (int i = 0; i < 10000; ++i) { std::lock_guard<std::mutex> lock(mtx); data.push_back(i); } } int main() { std::thread t1(task); std::thread t2(task); t1.join(); t2.join(); std::cout << data.size() << std::endl; }

输出:

20000

稳定。

九、锁的粒度问题(工程重点)

你这样写:

void task() { std::lock_guard<std::mutex> lock(mtx); for (int i = 0; i < 10000; ++i) { data.push_back(i); } }

锁范围更大。

优点:

  • 锁竞争少

缺点:

  • 阻塞时间更长

工程原则:

锁只保护“共享资源操作”,
不要把耗时操作放在锁里。

十、错误示例:锁太小

if (!data.empty()) { std::lock_guard<std::mutex> lock(mtx); data.pop_back(); }

问题:

data.empty() 没加锁。

可能:

线程 A 判断非空
线程 B pop 完
线程 A 再 pop → 崩溃

正确写法:

std::lock_guard<std::mutex> lock(mtx); if (!data.empty()) { data.pop_back(); }

十一、资源保护系统思维

写并发代码前问:

1️⃣ 这个数据是否共享?
2️⃣ 是否有写操作?
3️⃣ 锁由谁持有?
4️⃣ 锁范围是否最小化?

十二、死锁风险

死锁发生在:

  • 两个线程
  • 持有不同锁
  • 相互等待

例如:

线程 A:锁 m1 → 锁 m2
线程 B:锁 m2 → 锁 m1

工程规避方式:

统一加锁顺序。

十三、工程 Checklist

✅ 共享数据必须有唯一 mutex
✅ 永远使用 lock_guard(不要手动 lock/unlock)
✅ 判断 + 操作必须在同一锁内
✅ 锁只保护数据,不保护耗时操作


十四、Java 再类比总结

概念JavaC++
自动释放锁synchronizedlock_guard
手动锁ReentrantLockstd::mutex
异常安全JVM 保证RAII 保证

十五、本篇总结一句话

线程私有栈,共享堆;
共享必保护;
RAII 是 C++ 锁的灵魂。

下一篇预告

第三篇我们讲:

std::unique_lock —— 为什么它比 lock_guard 更“重”?

  • 为什么条件变量必须用 unique_lock?
  • 如何避免死锁?
  • defer_lock / try_lock 是干什么的?
  • 锁释放与再获取的工程场景

Read more

解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式

解锁DeepSeek潜能:Docker+Ollama打造本地大模型部署新范式

🐇明明跟你说过:个人主页 🏅个人专栏:《深度探秘:AI界的007》 🏅 🔖行路有良友,便是天堂🔖 目录 一、引言 1、什么是Docker 2、什么是Ollama 二、准备工作 1、操作系统 2、镜像准备 三、安装 1、安装Docker 2、启动Ollama 3、拉取Deepseek大模型 4、启动Deepseek  一、引言 1、什么是Docker Docker:就像一个“打包好的App” 想象一下,你写了一个很棒的程序,在自己的电脑上运行得很好。但当你把它发给别人,可能会遇到各种问题: * “这个软件需要 Python 3.8,但我只有 Python 3.6!

By Ne0inhk
深挖 DeepSeek 隐藏玩法·智能炼金术2.0版本

深挖 DeepSeek 隐藏玩法·智能炼金术2.0版本

前引:屏幕前的你还在AI智能搜索框这样搜索吗?“这道题怎么写”“苹果为什么红”“怎么不被发现翘课” ,。看到此篇文章的小伙伴们!请准备好你的思维魔杖,开启【霍格沃茨模式】,看我如何更新秘密的【知识炼金术】,我们一起来解锁更加刺激的剧情!友情提醒:《《《前方高能》》》 目录 在哪使用DeepSeek 如何对提需求  隐藏玩法总结 几个高阶提示词 职场打工人 自媒体创作 电商实战 程序员开挂 非适用场地 “服务器繁忙”如何解决 (1)硅基流动平台 (2)Chatbox + API集成方案 (3)各大云平台 搭建个人知识库 前置准备 下载安装AnythingLLM 选择DeepSeek作为AI提供商 创作工作区 导入文档 编辑  编辑 小编寄语 ——————————————————————————————————————————— 在哪使用DeepSeek 我们解锁剧情前,肯定要知道在哪用DeepSeek!咯,为了照顾一些萌新朋友,它的下载方式我放在下面了,拿走不谢!  (1)

By Ne0inhk
【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

【AI大模型】DeepSeek + 通义万相高效制作AI视频实战详解

目录 一、前言 二、AI视频概述 2.1 什么是AI视频 2.2 AI视频核心特点 2.3 AI视频应用场景 三、通义万相介绍 3.1 通义万相概述 3.1.1 什么是通义万相 3.2 通义万相核心特点 3.3 通义万相技术特点 3.4 通义万相应用场景 四、DeepSeek + 通义万相制作AI视频流程 4.1 DeepSeek + 通义万相制作视频优势 4.1.1 DeepSeek 优势 4.1.2 通义万相视频生成优势 4.2

By Ne0inhk
【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

【DeepSeek微调实践】DeepSeek-R1大模型基于MS-Swift框架部署/推理/微调实践大全

系列篇章💥 No.文章01【DeepSeek应用实践】DeepSeek接入Word、WPS方法详解:无需代码,轻松实现智能办公助手功能02【DeepSeek应用实践】通义灵码 + DeepSeek:AI 编程助手的实战指南03【DeepSeek应用实践】Cline集成DeepSeek:开源AI编程助手,终端与Web开发的超强助力04【DeepSeek开发入门】DeepSeek API 开发初体验05【DeepSeek开发入门】DeepSeek API高级开发指南(推理与多轮对话机器人实践)06【DeepSeek开发入门】Function Calling 函数功能应用实战指南07【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:本地部署与API服务快速上手08【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:Web聊天机器人部署指南09【DeepSeek部署实战】DeepSeek-R1-Distill-Qwen-7B:基于vLLM 搭建高性能推理服务器10【DeepSeek部署实战】基于Ollama快速部署Dee

By Ne0inhk