C++ 多线程实战 01|为什么需要线程:并发 vs 并行,进程 vs 线程

发布于:2025-09-02 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

一、为什么要学习多线程?

二、进程与线程的区别

1. 什么是进程?

2. 什么是线程?

3. 直观对比

三、并发 vs 并行

四、线程在程序中怎么工作?

五、代码示例:Hello, Thread!

运行效果

六、常见误区

七、练习题

八、总结


一、为什么要学习多线程?

想象一下你在写一个程序:

  • 它要同时下载文件、显示下载进度、还要让用户能随时点击暂停按钮。
    如果你用单线程来写,要么下载时界面卡死,要么响应界面时下载停掉。

解决方法就是 —— 多线程。
多线程能让程序同时处理多个任务,让应用更加流畅和高效。

但别急,我们先把几个基础概念理清楚,否则后面会很容易混淆。


二、进程与线程的区别

1. 什么是进程?

进程(Process)就是操作系统为一个正在运行的程序分配的独立资源空间

  • 每个进程有自己的 内存地址空间(代码段、数据段、堆、栈)。

  • 进程之间一般是隔离的,不能直接访问对方的数据。

  • 创建/销毁进程的开销比较大。

👉 可以把进程类比成“一个独立的公司”,有自己的办公室、员工和资源,外人进不来。


2. 什么是线程?

线程(Thread)是进程里的一个执行单元。

  • 一个进程至少有一个线程(主线程)。

  • 线程之间共享进程的地址空间(所以访问数据更方便)。

  • 创建/切换线程的开销比进程小。

👉 线程就像是“公司里的员工”,大家共用同一个办公室和资料,但可以同时干不同的活。


3. 直观对比

项目 进程 线程
地址空间 独立 共享
创建/切换开销
崩溃影响范围 一个进程崩溃一般不影响别的进程 一个线程崩溃可能拖垮整个进程
通信方式 IPC(管道、消息队列等) 共享内存,速度快

三、并发 vs 并行

这是很多初学者最容易混淆的概念。

  • 并发(Concurrency):逻辑上“同时”执行,但实际上可能是在一颗 CPU 上快速切换
    👉 就像一个人同时看两本书:看一页 A → 翻页 → 看一页 B → 再翻页 → 回来继续 A。

  • 并行(Parallelism):物理上真的同时执行,通常是多核 CPU 各干各的
    👉 就像两个人各拿一本书,各自读,不用切换。

📌 总结:

  • 并发 = 时间上交错,提升“响应性”;

  • 并行 = 空间上同时,提升“吞吐量”。


四、线程在程序中怎么工作?

  • 每个线程有自己的 (用来保存局部变量、函数调用信息)。

  • 线程共享 堆、全局变量、文件句柄 等资源。

  • 操作系统调度器负责分配 CPU 时间片,决定哪个线程什么时候运行。

👉 换句话说:线程是操作系统调度的最小单位。


五、代码示例:Hello, Thread!

我们用一个最简单的例子来感受一下:

#include <iostream>
#include <thread>

void say_hello(const std::string& name) {
    for (int i = 0; i < 5; i++) {
        std::cout << "Hello from " << name << " (i=" << i << ")\n";
    }
}

int main() {
    std::thread t1(say_hello, "thread-1");
    std::thread t2(say_hello, "thread-2");

    t1.join();  // 等待 t1 完成
    t2.join();  // 等待 t2 完成

    std::cout << "Main thread finished.\n";
    return 0;
}

运行效果

输出可能是这样的(顺序会乱):

Hello from thread-1 (i=0)
Hello from thread-2 (i=0)
Hello from thread-1 (i=1)
Hello from thread-2 (i=1)
...

👉 这里可以看到,两个线程的输出交错在一起,说明它们是并发执行的。


六、常见误区

  1. 线程一定会让程序更快?

    • 如果任务是 I/O 密集(比如网络、文件),线程确实能提高效率。

    • 但如果任务是纯计算密集(CPU 满载),线程数超过 CPU 核心数可能会更慢(上下文切换开销大)。

  2. 线程和进程谁更安全?

    • 进程更独立,一个崩溃不会影响其他。

    • 线程共享内存,出错时可能直接导致整个进程崩溃。


七、练习题

  1. 修改上面的代码,创建 4 个线程,分别打印不同的名字。

  2. 在主线程里也调用 say_hello("main"),看看输出会怎样交错。

  3. 如果把 t1.join() 改成 t1.detach(),结果会发生什么?


八、总结

  • 进程 = 程序的资源容器线程 = 执行单元

  • 并发 ≠ 并行:并发是“切换”,并行是“同时”。

  • 多线程的优势:提升程序响应性和吞吐量。

  • 但多线程也带来新问题:同步、数据竞争、死锁……(后续章节逐步展开)。


👉 下一篇文章:
「线程生命周期全景:创建、运行、终止、回收」
我们将深入讨论线程的出生到消亡的全过程,以及 join/detach 的区别。


网站公告

今日签到

点亮在社区的每一天
去签到