C++ 多线程编程:从入门到实战
C++ 多线程编程 超详细入门 + 实战指南
我会用最通俗、最实战、最容易理解 的方式,把 C++11 之后官方多线程库 \<thread\> 讲透,包含:
是什么、为什么用、怎么写、实战用法、坑点、项目真实场景
全程不绕弯,新手也能直接上手。
一、什么是多线程?为什么要用?
1. 通俗理解
单线程:一个人干活
多线程:多个人同时干活
2. 多线程解决什么问题?
-
提高效率:同时做多个任务(下载 + 解压 + 显示)
-
不卡顿:界面不卡死(UI 线程 + 工作线程)
-
充分利用 CPU 多核
-
高并发:服务器同时处理多个请求
3. C++ 多线程用什么库?
C++11 官方标准库:****\<thread\>
跨平台(Windows/Linux/Mac 通用)
二、最核心:4 个多线程基础组件
C++ 多线程必学 4 个东西:
-
std::thread创建线程 -
std::mutex互斥锁(解决数据安全) -
std::lock\_guard/std::unique\_lock自动锁 -
std::condition\_variable条件变量(线程通信)
三、最基础:创建一个线程
代码 + 逐行解释
cpp
#include <iostream>
#include <thread> // 多线程头文件
using namespace std;
// 线程要执行的函数
void func() {
cout << "子线程运行\n";
}
int main() {
thread t(func); // 1. 创建线程并启动
t.join(); // 2. 等待子线程结束(必须写!)
cout << "主线程结束\n";
return 0;
}
逐行解释
-
\#include \<thread\>:C++ 官方多线程头文件 -
void func\(\):子线程要跑的函数 -
thread t\(func\):创建线程对象t,并立刻开始运行func -
t\.join\(\):主线程等待子线程完成不写会崩溃!
四、线程的两种等待方式(必考)
1. join () ------ 等待线程完成
cpp
t.join();
主线程卡住,等子线程跑完再继续。
2. detach () ------ 分离线程
cpp
t.detach();
主线程不管子线程,各自运行
主线程退出,子线程会被强制杀死
五、多线程最大坑:数据安全问题(必须学)
多线程同时修改一个变量 = 数据错乱
必须用 互斥锁 mutex
1. 互斥锁 std::mutex
cpp
#include <mutex>
mutex mtx; // 定义一把锁
void func() {
mtx.lock(); // 加锁
// 操作共享数据
mtx.unlock(); // 解锁
}
作用
只允许一个线程进入代码区,避免数据混乱
2. 推荐写法:lock\_guard 自动锁
不用手动 lock/unlock,防止忘记解锁死锁
cpp
void func() {
lock_guard<mutex> lock(mtx); // 自动加锁
// 操作数据
} // 离开大括号自动解锁
六、实战最常用:线程传参
线程函数可以传:
普通参数、引用、指针、类成员函数
1. 传普通参数
cpp
void func(int a, string s) {
}
thread t(func, 10, "hello");
2. 传引用(必须加 std::ref)
cpp
void func(int &a) {
}
thread t(func, ref(a));
3. 类成员函数做线程函数
cpp
class Test {
public:
void work() {}
};
Test obj;
thread t(&Test::work, &obj); // 传对象地址
七、真正实战:生产者消费者模型(90% 项目用)
最经典、最常用、面试必考
场景:
-
生产线程:生产数据放入队列
-
消费线程:从队列取出数据处理
-
用
条件变量实现队列空时等待,有数据时唤醒
完整实战代码(可直接用)
cpp
#include <iostream>
#include <thread>
#include <mutex>
#include <queue>
#include <condition_variable>
using namespace std;
queue<int> q; // 数据队列
mutex mtx; // 互斥锁
condition_variable cv; // 条件变量
// 生产者
void producer() {
for (int i = 1; i <= 5; ++i) {
this_thread::sleep_for(chrono::seconds(1)); // 模拟生产耗时
lock_guard<mutex> lock(mtx);
q.push(i);
cout << "生产: " << i << endl;
cv.notify_one(); // 唤醒消费者
}
}
// 消费者
void consumer() {
while (true) {
unique_lock<mutex> lock(mtx);
// 队列空就等待
cv.wait(lock, [] { return !q.empty(); });
// 取数据
int val = q.front();
q.pop();
cout << "消费: " << val << endl;
if (val == 5) break;
}
}
int main() {
thread t1(producer);
thread t2(consumer);
t1.join();
t2.join();
return 0;
}
你能学到
-
线程创建
-
互斥锁
-
条件变量等待 / 唤醒
-
生产消费模型
-
真实项目通用架构
八、项目实战中多线程怎么用?(真实场景)
1. 日志系统
-
一个后台线程专门写日志
-
其他线程只发消息,不阻塞
2. 网络请求
-
UI 线程不卡顿
-
子线程下载 / 上传
3. 数据解析 / 解压 / 编码
-
音视频解码
-
图片压缩
4. 服务器高并发
-
一个连接一个线程
-
或线程池
5. 线程池(企业级必备)
批量管理线程,避免频繁创建销毁开销
项目 99% 用线程池,不是手动创建 thread
九、多线程三大坑(必须记住)
-
忘记 join ()/detach () → 程序崩溃
-
共享数据不加锁 → 数据错乱、程序崩溃
-
线程还在运行,对象已经销毁 → 悬空指针崩溃
十、超清晰总结(背会就够用)
-
thread** 创建线程** -
join\(\)** 等待,detach\(\)分离** -
mutex** 锁保证数据安全** -
lock\_guard** 自动锁,推荐使用** -
condition\_variable** 线程间通信** -
生产消费模型 = 多线程实战核心
-
项目里优先用线程池
(注:文档部分内容可能由 AI 生成)