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

C++11新特性_标准库_线程库_std::thread

C++11 引入了 <thread> 头文件,提供了 std::thread 类用于创建和管理线程。以下是完整的代码示例,涵盖线程的创建、参数传递、等待线程结束(join)、分离线程(detach)以及异常安全管理。

示例 1:基础线程创建与 join

#include <iostream>
#include <thread>
#include <chrono>  // 用于时间延迟// 普通函数作为线程入口
void thread_func(int id, const std::string& msg) {for (int i = 0; i < 3; ++i) {std::cout << "线程 " << id << ": " << msg << " (第" << i+1 << "次)" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(200));  // 线程休眠 200ms}
}int main() {// 创建线程,传递参数(值传递)std::thread t1(thread_func, 1, "Hello from t1");std::thread t2(thread_func, 2, "Hi from t2");std::cout << "主线程等待子线程完成..." << std::endl;// 等待线程执行完成(阻塞主线程)t1.join();t2.join();std::cout << "所有子线程完成,主线程结束" << std::endl;return 0;
}
输出说明
主线程等待子线程完成...
线程 1: Hello from t1 (第1次)
线程 2: Hi from t2 (第1次)
线程 1: Hello from t1 (第2次)
线程 2: Hi from t2 (第2次)
线程 1: Hello from t1 (第3次)
线程 2: Hi from t2 (第3次)
所有子线程完成,主线程结束
关键点
  • 线程创建std::thread t(func, args...) 构造函数接受线程入口函数和参数(参数默认值传递)。
  • join():主线程调用 t.join() 会阻塞,直到子线程 t 执行完毕。若不调用 join(),程序结束时若线程未完成会崩溃(std::terminate)。

示例 2:传递引用参数与 detach

若需要传递引用参数,需使用 std::ref 包装(否则参数会被拷贝)。detach() 会让线程独立运行,主线程不再管理其生命周期。

#include <iostream>
#include <thread>
#include <string>
#include <functional>  // 用于 std::ref// 线程函数(接收引用参数)
void modify_string(std::string& str) {std::this_thread::sleep_for(std::chrono::milliseconds(100));  // 模拟耗时操作str += " (modified by thread)";
}int main() {std::string msg = "Original message";// 传递引用参数(需用 std::ref 包装)std::thread t(modify_string, std::ref(msg));// 分离线程:子线程独立运行,主线程不再等待t.detach();// 主线程继续执行(可能与子线程并行)std::this_thread::sleep_for(std::chrono::milliseconds(200));  // 等待子线程完成修改std::cout << "最终消息: " << msg << std::endl;// 若主线程提前结束,未完成的子线程会被强制终止(不推荐!)return 0;
}
输出说明
最终消息: Original message (modified by thread)
关键点
  • 引用传递std::ref(msg) 确保线程函数接收的是 msg 的引用而非拷贝。
  • detach():分离后线程独立运行,若主线程提前结束(如未等待子线程完成),子线程可能被终止(需谨慎使用)。

示例 3:使用类成员函数与 RAII 管理线程

线程对象在销毁前必须被 join 或 detach,否则程序终止。可通过 RAII(资源获取即初始化)模式确保线程被正确管理。

#include <iostream>
#include <thread>
#include <stdexcept>class ThreadGuard {
private:std::thread& t;  // 引用外部线程对象
public:explicit ThreadGuard(std::thread& thread) : t(thread) {}~ThreadGuard() {if (t.joinable()) {  // 仅当线程可 join 时才 joint.join();}}// 禁止拷贝(线程不可复制)ThreadGuard(const ThreadGuard&) = delete;ThreadGuard& operator=(const ThreadGuard&) = delete;
};class MyClass {
public:void member_func(int repeat) {for (int i = 0; i < repeat; ++i) {std::cout << "成员函数线程执行第 " << i+1 << " 次" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100));}}
};int main() {MyClass obj;std::thread t(&MyClass::member_func, &obj, 3);  // 成员函数需绑定对象指针// 使用 RAII 确保线程被 joinThreadGuard guard(t);// 模拟主线程异常(如抛异常)try {throw std::runtime_error("主线程抛异常");} catch (const std::exception& e) {std::cout << "捕获异常: " << e.what() << std::endl;}// ThreadGuard 析构时自动 join 线程(即使主线程抛异常)return 0;
}
输出说明
成员函数线程执行第 1 次
成员函数线程执行第 2 次
成员函数线程执行第 3 次
捕获异常: 主线程抛异常
关键点
  • 成员函数作为线程入口:需绑定类对象指针(&obj)和成员函数指针(&MyClass::member_func)。
  • RAII 管理ThreadGuard 类在析构时自动 join 线程,避免因异常导致线程未 join 而程序终止。

示例 4:使用 Lambda 表达式创建线程

C++11 支持使用 Lambda 作为线程入口函数,适合简单的一次性任务。

#include <iostream>
#include <thread>
#include <vector>int main() {std::vector<std::thread> threads;  // 存储线程对象的容器// 创建 3 个线程,使用 Lambda 作为入口for (int i = 0; i < 3; ++i) {threads.emplace_back([i]() {std::cout << "Lambda 线程 " << i << " 启动" << std::endl;std::this_thread::sleep_for(std::chrono::milliseconds(100 * (i+1)));std::cout << "Lambda 线程 " << i << " 结束" << std::endl;});}// 等待所有线程完成for (auto& t : threads) {t.join();}std::cout << "所有 Lambda 线程完成" << std::endl;return 0;
}
输出说明
Lambda 线程 0 启动
Lambda 线程 1 启动
Lambda 线程 2 启动
Lambda 线程 0 结束
Lambda 线程 1 结束
Lambda 线程 2 结束
所有 Lambda 线程完成

注意事项

  1. 线程所有权std::thread 对象是可移动但不可复制的(std::thread t2 = t1 非法,需用 t2 = std::move(t1))。
  2. joinable() 检查:调用 join() 或 detach() 前需通过 t.joinable() 判断线程是否可操作(避免重复 join 或 detach 已分离的线程)。
  3. 资源生命周期:若线程引用了外部变量(如局部变量),需确保变量在线程结束前存活(避免悬垂引用)。
  4. 线程调度std::this_thread::yield() 可主动让出 CPU 时间片;std::this_thread::get_id() 可获取线程 ID。

通过以上示例,可以掌握 C++11 std::thread 的核心用法,包括线程创建、参数传递、生命周期管理及异常安全处理。

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

相关文章:

  • 【Bootstrap V4系列】学习入门教程之 表格(Tables)和画像(Figure)
  • STM32复盘总结——芯片简介
  • 动态规划算法精解(Java实现):从入门到精通
  • Zephyr RTOS架构下的固件升级
  • MySQL数据库上篇
  • CPU:AMD的线程撕裂者(Threadripper)系列
  • 高等数学-第七版-下册 选做记录 习题10-1
  • Python爬虫实战:获取易车网最新特定车型销量数据并分析,为消费者购车做参考
  • 快速集成 Flutter Shorebird 热更新
  • Qt 中基于 QTableView + QSqlTableModel 的分页搜索与数据管理实现
  • 仙盟创梦IDE-智能编程,编程自动备份+编程审计
  • AI 驱动的智能交通系统:从拥堵到流畅的未来出行
  • uc系统中常用命令、标准C库函数和系统调用
  • 从实列中学习linux shell9 如何确认 服务器反应迟钝是因为cpu还是 硬盘io 到底是那个程序引起的。cpu负载多高算高
  • yolov5 本地训练
  • 从读写分离到分布式服务:系统架构演进十阶段深度解析
  • 实验二 软件白盒测试
  • 对第三方软件开展安全测评,如何保障其安全使用?
  • 【项目设计】MySQL 连接池的设计
  • BN254 点压缩在 L2 中的应用
  • 纳米AI搜索体验:MCP工具的实际应用测试,撰写报告 / 爬虫小红书效果惊艳2
  • python数据分析(八):Pandas 文本数据处理
  • 邹晓辉教授十余年前关于围棋程序与融智学的思考,体现了对复杂系统本质的深刻洞察,其观点在人工智能发展历程中具有前瞻性意义。我们可以从以下三个维度进行深入解析:
  • MYSQL-设计表
  • Redis 主从复制部署
  • MIT XV6 - 1.2 Lab: Xv6 and Unix utilities - pingpong
  • 基于DQN的自动驾驶小车绕圈任务
  • OSPF路由协议配置
  • 数字智慧方案5867丨智慧建造(BIM技术智慧工地)在施工阶段的实践与应用方案(90页PPT)(文末有下载方式)
  • 手写 Vue 源码 === Vue3 设计思想