C++ 多线程编程:从入门到实战

C++ 多线程编程:从入门到实战

C++ 多线程编程 超详细入门 + 实战指南

我会用最通俗、最实战、最容易理解 的方式,把 C++11 之后官方多线程库 \<thread\> 讲透,包含:

是什么、为什么用、怎么写、实战用法、坑点、项目真实场景

全程不绕弯,新手也能直接上手。


一、什么是多线程?为什么要用?

1. 通俗理解

单线程:一个人干活

多线程:多个人同时干活

2. 多线程解决什么问题?

  • 提高效率:同时做多个任务(下载 + 解压 + 显示)

  • 不卡顿:界面不卡死(UI 线程 + 工作线程)

  • 充分利用 CPU 多核

  • 高并发:服务器同时处理多个请求

3. C++ 多线程用什么库?

C++11 官方标准库:****\<thread\>

跨平台(Windows/Linux/Mac 通用)


二、最核心:4 个多线程基础组件

C++ 多线程必学 4 个东西:

  1. std::thread 创建线程

  2. std::mutex 互斥锁(解决数据安全)

  3. std::lock\_guard / std::unique\_lock 自动锁

  4. 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;
}

逐行解释

  1. \#include \&lt;thread\&gt;:C++ 官方多线程头文件

  2. void func\(\):子线程要跑的函数

  3. thread t\(func\):创建线程对象t,并立刻开始运行func

  4. 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


九、多线程三大坑(必须记住)

  1. 忘记 join ()/detach () → 程序崩溃

  2. 共享数据不加锁 → 数据错乱、程序崩溃

  3. 线程还在运行,对象已经销毁 → 悬空指针崩溃


十、超清晰总结(背会就够用)

  1. thread** 创建线程**

  2. join\(\) ** 等待,detach\(\) 分离**

  3. mutex** 锁保证数据安全**

  4. lock\_guard** 自动锁,推荐使用**

  5. condition\_variable** 线程间通信**

  6. 生产消费模型 = 多线程实战核心

  7. 项目里优先用线程池

(注:文档部分内容可能由 AI 生成)

相关推荐
kkeeper~1 小时前
0基础C语言积跬步之自定义类型联合和枚举
c语言·开发语言·算法
邪修king1 小时前
C++map_set封装 : 红黑树底层迭代器以及仿函数的运用
android·c语言·数据结构·c++·b树
七夜zippoe1 小时前
DolphinDB自定义函数:UDF开发指南
开发语言·python·自定义函数·udf·dolphindb
weixin199701080161 小时前
[特殊字符] 电商库存扣减防超卖:分布式锁的三种实现(附Python源码)
开发语言·分布式·python
z落落1 小时前
C# 多态 + 函数重载(静态多态)+运算符重载
开发语言·c#
码不停蹄的玄黓1 小时前
Java 应用 CPU 过高排查全流程
java·开发语言·python
牟师傅敲代码1 小时前
第2章:底层时间驱动机制
c++
江畔柳前堤2 小时前
XZ09_Word和MD格式转换
开发语言·数据库·人工智能·python·深度学习·word
ZenosDoron2 小时前
malloc规范
java·开发语言