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

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

目录

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

二、进程与线程的区别

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 的区别。

http://www.xdnf.cn/news/19427.html

相关文章:

  • 6 种可行的方法:小米手机备份到电脑并恢复
  • js语言编写科技风格博客网站-详细源码
  • AI-调查研究-66-机器人 机械臂 软件算法体系:轨迹规划·视觉定位·力控策略
  • 网络层和数据链路层
  • 智能对话系统优化方案:解决响应偏差与个性化缺失问题
  • OpenStack网络类型解析
  • 超越Transformer:语言模型未来的认知革命与架构重构
  • 手写MyBatis第47弹:Interceptor接口设计与Invocation上下文传递机制--MyBatis动态代理生成与方法拦截的精妙实现
  • uniApp 混合开发全指南:原生与跨端的协同方案
  • shell编程基础入门-3
  • Ansible之playbook剧本
  • 【Spark Core】(三)RDD的持久化
  • nrf52840 解锁
  • Linux部署OSM本地服务测试环境
  • Ubuntu 25.10 Snapshot4 发布。
  • 电动两轮车手机导航投屏方案调研报告
  • 「日拱一码」076 深度学习——自然语言处理NLP
  • SOME/IP-SD中IPv4端点选项与IPv4 SD端点选项
  • Coze源码分析-工作空间-资源库-前端源码
  • 掌握正则表达式与文本处理:提升 Shell 编程效率的关键技巧
  • FFmpeg 不同编码的压缩命令详解
  • 【扩充位数三位变五位】2022-10-30
  • mysql导出csv中字段里有换行符的处理办法及hive导出处理办法
  • 【php反序列化字符串逃逸】
  • Go 面试题: new 和 make 是什么,差异在哪?
  • ADSL 代理 Proxy API 申请与使用指南
  • NLP技术突破:浅层与深层语义分析全解析
  • test隐藏能力
  • 5-ATSAM3X8-定时器
  • 架构选型:为何用对象存储替代HDFS构建现代数据湖