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

HoRain云--C++多线程编程

🎬 HoRain 云小助手:个人主页

⛺️生活的理想,就是为了理想的生活!


⛳️ 推荐

前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。

目录

⛳️ 推荐

一、std::thread—— 线程本体

二、互斥与 RAII 锁 —— 对应 Java 的 synchronized

三、condition_variable—— 生产者-消费者标配

四、std::atomic与内存序 —— C++ 独有的深坑

五、future/ promise/ async—— 异步任务

六、C++20 新增值得提一嘴

七、跟 Java 多线程的对照(面试能串)

八、工程现实的两个"不像 Java"的点

九、几句面试加分


C++ 多线程跟 Java 那条线比,最大感受是"晚熟但贴硬件"——Java 出生就带Thread/synchronized,C++ 熬到C++11 才把<thread>/<mutex>/<atomic>/<future>收进标准,之前全靠 pthread / WinAPI / Boost。所以现在聊"C++ 多线程"默认指C++11/14/17/20 标准库,下面按"线程 → 锁 → 条件变量 → 原子 → 异步 → C++20 新增 → 跟 Java 对照的坑"走。


一、std::thread—— 线程本体

#include <thread> #include <iostream> using namespace std; void task(int x) { cout << x << endl; } int main() { thread t(task, 42); // 传可调用对象 + 参数(参数会拷贝进线程) if (t.joinable()) { t.join(); // 等它跑完 // t.detach(); // 或分离,后台跑,主线程不管了 } }

几个跟 Java 立刻不同的点:

💡 C++20 的std::jthread​ 才是"现代首选"——析构自动join(),还带std::stop_token协作式中断,不用自己写取消标志位了。


二、互斥与 RAII 锁 —— 对应 Java 的synchronized

mutex m; int cnt = 0; void add() { lock_guard<mutex> lk(m); // 构造加锁,析构解锁,noexcept ++cnt; } // 出作用域自动 unlock,异常也安全

C++ 没有finally锁的释放全靠 RAII 析构——这是跟 Java 的根本差异(Java 靠synchronized块或ReentrantLock+try/finally)。

锁家族:

类型

用途

std::mutex

基础互斥,不可拷贝

std::recursive_mutex

同一线程可重复加锁(慎用,设计味道)

std::timed_mutex

try_lock_for()超时版

std::shared_mutex(C++17)

读写锁,读多写少场景

RAII 壳子俩兄弟:

死锁防护——C++17 的std::scoped_lock:一次锁多个,内部按地址排序加锁,无论你传的顺序咋样都不会死锁:

scoped_lock lk(m1, m2, m3); // 同时锁三个,不会死锁

对标 Java 的"锁排序"套路,但 C++ 标准库直接给你包好了。


三、condition_variable—— 生产者-消费者标配

跟 Java 的wait()/notify()长得很像,但两个坑 Java 程序员过来容易栽

mutex m; condition_variable cv; queue<int> q; bool done = false; // 消费者 void consumer() { unique_lock<mutex> lk(m); cv.wait(lk, []{ return !q.empty() || done; }); // while 谓词版,防虚假唤醒 // ... } // 生产者 void producer() { { lock_guard<mutex> lk(m); q.push(1); } // 通知前解锁,减少被唤醒线程的抢锁争用 cv.notify_one(); }

关键点:

  1. 必须配unique_lock(不是lock_guard——因为wait()要原子地释放锁 + 挂起,唤醒后重新加锁

  2. wait(lk, predicate)用谓词重载,等价于while(!pred) wait(lk)——防虚假唤醒(spurious wakeup),这是 POSIX / Java / C++ 三边共有的,Java 也要求whileif,但 C++ 这重载帮你包了一层

  3. notify_one()/notify_all()—— 通知不需要持锁(标准允许多种做法,但推荐通知前解锁减少争用)

  4. 还有个condition_variable_any,能配任意BasicLockable(含shared_lock),但慢一点


四、std::atomic与内存序 —— C++ 独有的深坑

Java 那边volatile只保可见性不保原子性,得VarHandleAtomicInteger;C++ 的std::atomic一步到位,还多了六级内存序——这是 Java 程序员过来最容易懵的地方。

atomic<bool> ready{false}; int data = 0; void producer() { data = 42; ready.store(true, memory_order_release); // 前面的写不会被重排到 store 之后 } void consumer() { while (!ready.load(memory_order_acquire)) // 后面的读不会被重排到 load 之前 ; assert(data == 42); // 永不为真?不,acquire-release 保证了能看到 42 }

六级memory_order

含义

场景

relaxed

只保原子性,不管可见性顺序

计数器

consume

数据依赖链同步(C++26 弃用,实际被 acquire 替)

acquire

load 用,之后的读写不许重排到 load 前

读标志后读数据

release

store 用,之前的读写不许重排到 store 后

写完数据设标志

acq_rel

read-modify-write 用,双向屏障

CAS、fetch_add

seq_cst

全序,默认档,所有原子操作全局一致顺序

调试、保守写法

Release-Acquire 配对是 C++ 无锁编程的命门:release 之前的所有写,对配对 acquire 成功读到该值的线程全部可见——上面那个producer/consumer例子就是这个语义,等价于 Java 的"volatile 写 + volatile 读"但 C++ 更精细可控。

⚠️ 默认seq_cst最安全但最慢(全内存屏障);无锁代码调优才往下换 acquire/release;relaxed只在"我只关心这个变量原子性、不关心别的可见性"时才用(比如纯计数器)。


五、future/promise/async—— 异步任务

对应 Java 的Future/CompletableFuture,但 C++ 这套更"裸":

auto fut = async([] { this_thread::sleep_for(1s); return 42; }); cout << fut.get() << endl; // 阻塞等结果,只能 get 一次

💡 想要 JavaCompletableFuture那种thenApply/thenCompose链式?C++ 标准库没有,得自己拼或用std::experimental::future(很少用),或者上第三方(folly::Future、Qt 等)。


六、C++20 新增值得提一嘴


七、跟 Java 多线程的对照(面试能串)

维度

Java

C++

线程本体

Thread/ 线程池

std::thread/jthread

互斥

synchronized/ReentrantLock

std::mutex+ RAII(lock_guard/unique_lock

读写锁

ReentrantReadWriteLock

std::shared_mutex(C++17)

等待/通知

wait()/notify()(Object)

condition_variable+unique_lock

原子类

AtomicInteger

std::atomic<T>+ 六级内存序

异步

CompletableFuture

std::future/async(无链式)

内存模型

happens-before,volatile 弱

六级memory_orderseq_cst默认

协程

Project Loom 虚拟线程(JDK 21)

C++20 协程(底层,无 runtime)

死锁防护

锁排序 /tryLock(timeout)

scoped_lock(C++17,自动排序)


八、工程现实的两个"不像 Java"的点

1. 不是所有 C++ 项目都用std::thread

游戏引擎、高频交易、嵌入式——要么禁用异常 + 禁用 RTTI + 自己线程池,要么直接 pthread / 平台 API。std::thread在那些场景被认为"抽象过重 + 不可控"(join 模型、异常传播、TLS 行为)。

2. 线程参数传递是高频坑

void f(int& x) { x++; } int val = 0; thread t(f, val); // ❌ 编译不过,参数被拷贝,引用传不进去 thread t(f, ref(val)); // ✅ 必须 std::ref

局部变量指针传给detach()的线程 = 野指针经典案,Java 没有这问题(GC 兜着)。


九、几句面试加分


如果想再往下挖,可以聊C++20 协程的co_await到底怎么串异步 IO无锁队列怎么用 acquire-release 搭,或者memory_order_seq_cst为什么比 acquire-release 慢一个量级——挑一个?

❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

http://www.cnnetsun.cn/news/3126598.html

相关文章:

  • 《唤醒你的AI同事:WorkBuddy从零上手》035:工作流程优化
  • 长文档总结不卡顿,128k 上下文在 Strix Halo 上的表现
  • Gemini 1.5与GPT-4o真实对比:大模型选型的技术逻辑与落地实践
  • 垃圾短信识别项目深度复盘:中文文本分类全流程实战 + 3 个数据泄漏避坑指南
  • AI赋能非技术行业实战:我用DeepSeek+混元整理了2026河北高考志愿填报完整指南
  • DeepSeek 开源 DSpark,一个可将 LLM 推理速度提升高达 85% 的新框架
  • 【ROS】 ros学习日记(1)
  • swagger增强knife4j
  • C++:拷贝构造函数
  • 椭圆曲线 Diffie-Hellman 密钥交换解题思路
  • 集团知识管理平台建设方案:74页PpT爆款干货全解析!
  • 【2026万字实录】从理论到实战:网络信息安全全景深度解析与避坑指南
  • 后 Django 时代:SQLAlchemy 2.0、Tortoise 与 Piccolo 三大异步 ORM 选型指南
  • 几分钟完成 OpenClaw 安装,Windows 可视化步骤新手直接照搬
  • 手撕字符串算法:反转、回文、验证回文 Ⅱ 完整拆解
  • 带标注的骑电动车是否佩戴头盔数据集,识别率77.1%,1345张图,支持yolo,coco json,voc xml,文末有模型训练代码
  • 3个核心功能解决你的Windows日志分析困境:为什么LogExpert能成为开发运维的终极利器?
  • DellFanManagement:戴尔笔记本终极风扇控制解决方案,告别噪音与过热烦恼!
  • 预约留资小程序制作工具测评:餐宝盈/BBWEYY/比文云/Landingi/Webnode(2026年7月更新)含零代码SAAS、AI编程、源码定制交付
  • GPT-4o与文心一言4.5:当前主流大模型真实进展解析
  • 芯原推出CPP2000摄像头后处理IP,赋能具身机器人和移动视觉应用
  • 云系列和Terraform(十二)
  • WidescreenFixesPack:让70+款经典游戏在现代宽屏显示器上完美运行的终极方案
  • Claude为什么这么聪明?揭秘藏在每个AI大模型背后的“注意力魔法“
  • 02-SpringBoot配置文件
  • 华为MetaERP OM 一致性对账 SQL 脚本集合(OM-WSH、WSH-INV、OM-AR、异常订单筛查)
  • 无感FOC与滑膜观测器在电机控制中的应用
  • 建筑外立面缺陷智能识别:YOLOv26驱动下的多类损伤检测数据集与实战10748期
  • 1kW高效BLDC电机设计:医疗设备应用与转矩脉动控制
  • 保姆级外部字幕添加教程 3步搞定播放器字幕加载