当前位置: 首页 > news >正文

C++ 多线程与并发系统取向(一)—— 从线程模型开始(类比 Java 理解)

一、为什么必须先讲“线程模型”?

很多人学 C++ 多线程,是从std::thread开始的。

但问题是:

你真的知道线程在“并发什么”吗?

如果你不知道线程共享什么、隔离什么,你就不知道应该保护什么。

这就是并发系统取向的第一步:

先理解线程模型,再谈加锁。

二、进程 vs 线程(Java 类比)

1️⃣ 进程是什么?

操作系统中的资源单位。

  • 拥有独立内存空间
  • 拥有文件描述符
  • 拥有自己的地址空间

在 Java 中:

  • 每个 JVM 进程就是一个独立进程
  • 运行一个java -jar xxx.jar就是启动一个进程

2️⃣ 线程是什么?

线程是:

CPU 调度的最小单位

  • 同一个进程内的线程
  • 共享同一块内存空间
  • 共享堆
  • 共享全局变量

但:

  • 每个线程有自己的栈

3️⃣ C++ vs Java 对比

项目C++Java
创建线程std::threadnew Thread()
内存模型共享堆共享堆
每线程独立每线程独立
垃圾回收有 GC
资源释放手动JVM 管理

⚠ 关键区别:

C++ 没有 GC。

所以c++在多线程中管理的是:

  • 数据竞争
  • 资源释放
  • 生命周期

风险比 Java 大。

三、线程到底“共享”什么?

每个线程:

拥有:

  • 自己的栈
  • 自己的函数调用链
  • 自己的局部变量

所有线程共享:

  • 全局变量
  • 静态变量
  • 堆内存
  • 文件
  • socket

四、最重要概念:数据竞争(Data Race)

如果:

  • 两个线程
  • 同时访问同一个变量
  • 至少一个在写
  • 没有同步手段

那就是:

数据竞争(Undefined Behavior)

注意:

不是“结果错误”。

而是:

未定义行为。

可能对,可能错,可能崩溃。

五、最小示例:C++ 数据竞争

#include <iostream> #include <thread> int counter = 0; void task() { for (int i = 0; i < 100000; ++i) { counter++; } } int main() { std::thread t1(task); std::thread t2(task); t1.join(); t2.join(); std::cout << counter << std::endl; }

你猜结果是多少?

理论上:

200000

实际可能:

173456 189234 200000

原因:

counter++ 不是原子操作

它其实是:

  1. 读取
  2. 加 1
  3. 写回

两个线程可能交错执行。

六、Java 对比这个例子

Java 代码:

static int counter = 0; static void task() { for (int i = 0; i < 100000; i++) { counter++; } }

结果一样会错。

Java 解决方式:

  • synchronized
  • AtomicInteger

C++ 对应:

  • std::mutex
  • std::atomic

七、线程生命周期(必须理解)

1️⃣ 创建

C++:

std::thread t(task);

Java:

new Thread(() -> task()).start();

2️⃣ join(等待结束)

C++:

t.join();

Java:

t.join();

几乎一样。

3️⃣ detach(危险)

C++ 允许:

t.detach();

线程变成“后台线程”。

主线程退出:

进程结束 → 所有线程被杀。

⚠ 工程里:

99% 不要用 detach

Java 没有这种用法(你不能让 JVM 不知道线程状态)。

八、线程模型核心图(必须记住)

进程 ├── 线程1(独立栈) ├── 线程2(独立栈) └── 线程3(独立栈) 共享: 堆 全局变量 静态变量

九、系统取向思维:你要问的 3 个问题

写任何并发代码前,问自己:

1️⃣ 这个数据是否被多个线程访问?
2️⃣ 是否存在写操作?
3️⃣ 谁负责保护它?

如果第 1 + 第 2 = YES

那就必须同步。

十、C++ 并发的风险比 Java 高在哪?

Java:

  • 有 GC
  • 有内存模型规范
  • synchronized 语义强

C++:

  • 没 GC
  • 锁用错直接 UB
  • 原子用错更隐蔽
  • 资源释放需要你自己管

但:

C++ 性能控制能力更强。

十一、本篇总结

线程模型核心记住一句话:

线程私有栈,共享堆;
共享即风险;
写必加锁。

十二、下一篇预告

下一篇我们进入:

资源保护(一):std::mutex 与 lock_guard

我们会讲:

  • 什么是临界区
  • 为什么 RAII 是 C++ 的核心思想
  • lock_guard 为什么比手动 lock/unlock 安全
  • 锁的粒度怎么设计
http://www.jsqmd.com/news/402732/

相关文章:

  • 基于大模型的智能客服方案:架构设计与工程实践
  • 斑头雁智能客服系统入门指南:从零搭建高可用对话引擎
  • 真的太省时间!专科生专用的降AIGC工具 —— 千笔·降AIGC助手
  • Java智能客服系统架构优化实战:从高延迟到毫秒级响应
  • 少走弯路:9个AI论文软件测评!本科生毕业论文写作必备工具推荐
  • Chromium WebRTC调试实战:从基础配置到高效问题定位
  • 2026年斯沃琪手表维修推荐:专业售后中心深度评价,涵盖维修与保养核心场景 - 十大品牌推荐
  • 救命神器!千笔写作工具,继续教育论文写作救星
  • CoolEdit播放PCM音频的技术实现与性能优化指南
  • 手表维修哪个服务好?2026年广州泰格豪雅手表维修推荐与排名,针对售后与时效痛点 - 十大品牌推荐
  • ChatTTS使用说明:从技术原理到高效部署的完整指南
  • ChatGLM2 Chatbot 错误处理实战:从异常诊断到效率提升
  • 基于python的临时工调配工资管理系统
  • ChatGPT润色指令实战:如何用AI提升办公文档处理效率
  • ChatTTS 模型自训练实战:从零构建个性化语音合成系统
  • Zustand 不可变更新深度解析
  • 基于CosyVoice A100的AI辅助开发实战:从语音模型集成到生产环境优化
  • 银行智能客服系统技术调研:从架构设计到生产环境落地
  • Zustand store深度解析
  • CLine 提示词实战指南:从基础原理到高效应用
  • 电商智能客服Agent工作流架构设计与性能优化实战
  • ChatTTS 声音克隆技术解析:从原理到工程实践
  • ChatGPT APK 百度网盘分发实战:安全部署与性能优化指南
  • CosyVoice 在 CPU 环境下的部署与优化:新手入门指南
  • ChatTTS 在 Win11 上的完整安装指南:从环境配置到避坑实践
  • STM32偏硬件的毕业设计入门指南:从选型到简单项目实战
  • 基于python地铁站设施设备查询系统设计
  • 微电子科学与工程毕设实战:基于FPGA的低功耗信号采集系统设计与实现
  • 简历里最值钱的一句话:怎么写出来?
  • 信息安全毕设检测系统源码入门:从零构建一个可扩展的检测框架