c++:线程(std::thread)

[复制链接]
发表于 2025-9-22 23:23:32 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
目次
从第一性原理出发:为什么须要线程?
 ✅ 本质界说:
📌 使用根本语法:  
线程之间的“并发”与“并行”的区别
 线程安全与数据竞争(Race Condition)
如何让线程“安全地”访问数据? 
完备示例:使用线程加速加法 


从第一性原理出发:为什么须要线程?

想象一下:
你有一个步调,它要做许多事,好比:


  • 下载文件
  • 处理图片
  • 打印日记
  • 相应用户输入假如这些使命按次序来(单线程),那用户体验就会很差:好比下载还没完,界面就卡住了。
第一性标题来了: 
能不能让步调同时做多件事,而不是排队一个个来? 
 能!用线程! 
 ✅ 本质界说:

 线程(Thread)是步调内部能并发实行的最小单元。
线程 = 步调里可以独立并发实行的一段使命。 
一个步调至少有一个线程(主线程),你可以再创建多个线程来同时实行差别的代码块。
📌 使用根本语法:  

  1. #include <thread>
复制代码
 std::thread 类就是 C++ 提供的“创建和管理线程”的工具。
  1. #include <iostream>#include <thread>
  2. void work() {    std::cout << "工作线程正在运行\n";}int main() {    std::thread t(work);  // 创建一个线程实行 work()    t.join();             // 等候这个线程实行完    std::cout << "主线程竣事\n";}
复制代码
表明:


  • std::thread t(work);:创建了一个“工人线程”,去实行函数 work
  • t.join();:告诉主线程“等工人做完再走”
  • 末了主线程输出“主线程竣事”
创建线程的三种方式:
方法示例传函数名(函数指针)std::thread t(func);
传 lambda 表达式std::thread t([](){ ... });传函数对象(仿函数)std::thread t(Functor());  线程的控制使用(join 和 detach)
  1. std::thread t(func);
复制代码
你创建了一个新线程,但它和主线程是“并行运行的”。
 接下来你必须做一件事(二选一):
使用阐明t.join()等候这个线程运行竣事,和主线程“合并”t.detach()把线程“放飞”,让它本身跑,主线程不再管它(配景线程) C++ 尺度要求:每个 std::thread 对象 在烧毁前必须被 join 或 detach! 
留意:主线程大概在子线程还没竣事时就退出了,这种线程叫做 配景线程。 
线程之间的“并发”与“并行”的区别

概念寄义并发(concurrent)逻辑上“同时”运行,现实上轮替交替实行(单核CPU)并行(parallel)真正的同时实行(多核CPU,每个线程跑在差别核上)  线程安全与数据竞争(Race Condition)

多个线程访问同一块数据会出标题! 
  1. int counter = 0;
  2. void add() {
  3.     for (int i = 0; i < 100000; ++i)
  4.         ++counter;
  5. }
  6. int main() {
  7.     std::thread t1(add);
  8.     std::thread t2(add);
  9.     t1.join();
  10.     t2.join();
  11.     std::cout << counter << std::endl;  // ❓ 输出不是 200000?!
  12. }
复制代码
为什么?


  • 由于两个线程在同时修改同一个变量
  • 出现了所谓的 数据竞争(Race Condition)
如何让线程“安全地”访问数据? 

使用互斥锁(std::mutex) 
  1. #include <mutex>
  2. std::mutex mtx;
  3. void add() {
  4.     for (int i = 0; i < 100000; ++i) {
  5.         std::lock_guard<std::mutex> lock(mtx);  // 自动加锁/解锁
  6.         ++counter;
  7.     }
  8. }
复制代码
 使用 lock_guard 是今世 C++ 推荐的做法,RAII 主动开释锁。
完备示例:使用线程加速加法 

  1. #include <iostream>#include <thread>
  2. void printRange(int start, int end) {    for (int i = start; i <= end; ++i)        std::cout << i << " ";}int main() {    std::thread t1(printRange, 1, 50);    std::thread t2(printRange, 51, 100);    t1.join();    t2.join();    std::cout << "\nDone\n";}
复制代码
 输出大概是:
  1. 1 2 3 51 52 53 ... 50 100
复制代码
次序是“乱的”!由于是并发实行的结果。 
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表