C++并发编程指南02

文章目录

      • 线程的基本操作
        • 2.1.1 启动线程
          • 基本启动方法
          • 使用函数对象
          • 避免“最令人头痛的语法解析”
        • 2.1.2 等待线程完成
          • 使用`join()`等待线程结束
          • 使用`detach()`分离线程
          • RAII方式等待线程完成
        • 2.1.3 特殊情况下的等待
        • 2.1.4 后台运行线程
          • 示例:使用分离线程处理文档
      • 总结

线程的基本操作

2.1.1 启动线程

每个C++程序至少包含一个执行main()函数的主线程。其他线程可以与主线程并行运行,当线程完成其指定任务(即函数执行完毕)时,它们也会自然退出。启动新线程通常通过创建std::thread对象来实现。

基本启动方法
void do_some_work();
std::thread my_thread(do_some_work);
  • 包含头文件:需要包含<thread>以使用C++标准库中的多线程功能。
  • 构造函数std::thread可以通过函数指针或函数对象进行构造,并在创建时自动启动线程。
使用函数对象
class background_task {
public:void operator()() const {do_something();do_something_else();}
};background_task f;
std::thread my_thread(f);
  • 复制机制:函数对象会被复制到新线程的存储空间中,在那里执行和调用。
避免“最令人头痛的语法解析”

传递临时变量而非命名变量可能导致编译器误将其解析为函数声明:

// 错误示例
std::thread my_thread(background_task());// 正确示例
std::thread my_thread((background_task()));  // 1
std::thread my_thread{background_task()};    // 2
  • Lambda表达式:避免上述问题的有效方法之一是使用Lambda表达式:
std::thread my_thread([]{do_something();do_something_else();
});
2.1.2 等待线程完成

为了确保线程正确结束,可以使用join()detach()方法。

使用join()等待线程结束
std::thread my_thread(do_some_work);
my_thread.join();  // 主线程等待my_thread完成
  • 作用join()使主线程等待直到新线程完成其任务。
使用detach()分离线程
struct func {int& i;func(int& i_) : i(i_) {}void operator() () {for (unsigned j = 0; j < 1000000; ++j) {do_something(i);  // 潜在访问隐患:空引用}}
};void oops() {int some_local_state = 0;func my_func(some_local_state);std::thread my_thread(my_func);my_thread.detach();  // 不等待线程结束
}  // 函数返回后,some_local_state被销毁,但新线程可能仍在运行
  • 风险:如果线程还在运行而函数已返回,可能会导致对已销毁局部变量的非法访问,造成未定义行为。
RAII方式等待线程完成

为了避免异常情况下线程资源泄露,可以使用RAII模式:

class thread_guard {std::thread& t;
public:explicit thread_guard(std::thread& t_) : t(t_) {}~thread_guard() {if (t.joinable()) {t.join();}}thread_guard(thread_guard const&) = delete;thread_guard& operator=(thread_guard const&) = delete;
};void f() {int some_local_state = 0;func my_func(some_local_state);std::thread t(my_func);thread_guard g(t);do_something_in_current_thread();
}  // 自动调用thread_guard的析构函数,确保线程正确结束
2.1.3 特殊情况下的等待

在某些情况下,需要更灵活地控制线程的等待,例如超时等待或检查线程是否已经结束。这些需求可以通过条件变量和future等机制实现。

2.1.4 后台运行线程

使用detach()可以让线程在后台独立运行,脱离与主线程的直接联系:

std::thread t(do_background_work);
t.detach();
assert(!t.joinable());
  • 守护线程:分离线程通常称为守护线程,适用于长时间运行的任务,如文件系统监控、缓存清理等。
示例:使用分离线程处理文档
void edit_document(std::string const& filename) {open_document_and_display_gui(filename);while (!done_editing()) {user_command cmd = get_user_input();if (cmd.type == open_new_document) {std::string const new_name = get_filename_from_user();std::thread t(edit_document, new_name);  // 1t.detach();  // 2} else {process_user_input(cmd);}}
}
  • 传参启动线程:不仅可以向std::thread构造函数传递函数名,还可以传递函数所需的参数。

总结

通过掌握std::thread对象的创建、启动、等待和分离等基本操作,可以有效地管理并发任务。使用RAII模式可以确保即使在异常情况下也能正确释放线程资源。对于长时间运行的任务,分离线程提供了一种简便的方式来管理后台任务。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/9671.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

7. 马科维茨资产组合模型+金融研报AI长文本智能体(Qwen-Long)增强方案(理论+Python实战)

目录 0. 承前1. 深度金融研报准备2. 核心AI函数代码讲解2.1 函数概述2.2 输入参数2.3 主要流程2.4 异常处理2.5 清理工作2.7 get_ai_weights函数汇总 3. 汇总代码4. 反思4.1 不足之处4.2 提升思路 5. 启后 0. 承前 本篇博文是对前两篇文章&#xff0c;链接: 5. 马科维茨资产组…

推动知识共享的在线知识库实施与优化指南

内容概要 在当今迅速发展的数字化时代&#xff0c;在线知识库的实施显得尤为重要。它不仅为企业提供了高效的信息存储与共享平台&#xff0c;还能够有效促进团队成员之间的协作与知识传递。通过集中管理企业内的各类知识资源&#xff0c;在线知识库帮助员工快速查找所需信息&a…

51单片机开发:串口通信

实验目标&#xff1a;电脑通过串口将数据发送给51单片机&#xff0c;单片机原封不动地将数据通过串口返送给电脑。 串口的内部结构如下图所示&#xff1a; 串口配置如下&#xff1a; TMOD | 0X20 ; //设置计数器工作方式 2 SCON 0X50 ; //设置为工作方式 1 PCON 0X80 ; …

【电工基础】2.低压带电作业定义,范围,工作要求,电工基本工具

一。低压带电作业 1.低压带电作业定义 低压带电作业是指在不停电的低压设备或低压线路上的工作。对于一些可以不停电的工作&#xff0c;没有偶然触及带电部分的危险工作&#xff0c;或作业人员使用绝缘辅助安全用具直接接触带电体及在带电设备外壳上的工作&#xff0c;均可进行…

C++ 中用于控制输出格式的操纵符——setw 、setfill、setprecision、fixed

目录 四种操纵符简要介绍 setprecision基本用法 setfill的基本用法 fixed的基本用法 setw基本用法 以下是一些常见的用法和示例&#xff1a; 1. 设置字段宽度和填充字符 2. 设置字段宽度和对齐方式 3. 设置字段宽度和精度 4. 设置字段宽度和填充字符&#xff0c;结合…

MYSQL 商城系统设计 商品数据表的设计 商品 商品类别 商品选项卡 多表查询

介绍 在开发商品模块时&#xff0c;通常使用分表的方式进行查询以及关联。在通过表连接的方式进行查询。每个商品都有不同的分类&#xff0c;每个不同分类下面都有商品规格可以选择&#xff0c;每个商品分类对应商品规格都有自己的价格和库存。在实际的开发中应该给这些表进行…

2025春晚刘谦魔术揭秘魔术过程

2025春晚刘谦魔术揭秘魔术过程 首先来看全过程 将杯子&#xff0c;筷子&#xff0c;勺子以任意顺序摆成一排 1.筷子和左边物体交换位置 2.杯子和右边物体交换位置 3.勺子和左边物体交换位置 最终魔术的结果是右手出现了杯子 这个就是一个简单的分类讨论的问题。 今年的魔术…

具身智能研究报告

参考&#xff1a; &#xff08;1&#xff09;GTC大会&Figure&#xff1a;“具身智能”奇点已至 &#xff08;2&#xff09;2024中国具身智能创投报告 &#xff08;3&#xff09;2024年具身智能产业发展研究报告 &#xff08;4&#xff09;具身智能行业深度&#xff1a;发展…

将ollama迁移到其他盘(eg:F盘)

文章目录 1.迁移ollama的安装目录2.修改环境变量3.验证 背景&#xff1a;在windows操作系统中进行操作 相关阅读 &#xff1a;本地部署deepseek模型步骤 1.迁移ollama的安装目录 因为ollama默认安装在C盘&#xff0c;所以只能安装好之后再进行手动迁移位置。 # 1.迁移Ollama可…

VPR概述、资源

SOTA网站&#xff1a; Visual Place Recognition | Papers With Code VPR&#xff08;Visual Place Recognition&#xff09; 是计算机视觉领域的一项关键任务&#xff0c;旨在通过图像匹配和分析来识别场景或位置。它的目标是根据视觉信息判断某个场景是否与数据库中的场景匹…

(Java版本)基于JAVA的网络通讯系统设计与实现-毕业设计

源码 论文 下载地址&#xff1a; ​​​​c​​​​​​c基于JAVA的网络通讯系统设计与实现(源码系统论文&#xff09;https://download.csdn.net/download/weixin_39682092/90299782https://download.csdn.net/download/weixin_39682092/90299782 第1章 绪论 1.1 课题选择的…

MySQL中的读锁与写锁:概念与作用深度剖析

MySQL中的读锁与写锁&#xff1a;概念与作用深度剖析 在MySQL数据库的并发控制机制中&#xff0c;读锁和写锁起着至关重要的作用。它们是确保数据在多用户环境下能够正确、安全地被访问和修改的关键工具。 一、读锁&#xff08;共享锁&#xff09;概念 读锁&#xff0c;也称为…

用HTML、CSS和JavaScript实现庆祝2025蛇年大吉(附源码)

用HTML、CSS和JavaScript庆祝2025蛇年大吉 在这个数字化时代&#xff0c;网页设计不仅仅是为了展示信息&#xff0c;更是传达情感和文化的一种方式。2025年将是蛇年&#xff0c;许多人希望通过各种方式庆祝这一重要的时刻。在这篇文章中&#xff0c;我们将一起学习如何使用HTM…

STM32标准库移植RT-Thread nano

STM32标准库移植RT-Thread Nano 哔哩哔哩教程链接&#xff1a;STM32F1标准库移植RT_Thread Nano 移植前的准备 stm32标准库的裸机代码&#xff08;最好带有点灯和串口&#xff09;RT-Thread Nano Pack自己的开发板 移植前的说明 本人是在读学生&#xff0c;正在学习阶段&a…

Unity 粒子特效在UI中使用裁剪效果

1.使用Sprite Mask 首先建立一个粒子特效在UI中显示 新建一个在场景下新建一个空物体&#xff0c;添加Sprite Mask组件&#xff0c;将其的Layer设置为UI相机渲染的UI层&#xff0c; 并将其添加到Canvas子物体中&#xff0c;调整好大小&#xff0c;并选择合适的Sprite&#xff…

JVM栈溢出线上环境排查

#查看当前Linux系统进程ID、线程ID、CPU占用率&#xff08;-eo后面跟想要展示的列&#xff09; ps H -eo pid,tid,%cpups H -eo pid,tid,%cpu |grep tid #使用java jstack 查看进程id下所有线程id的情况 jstack pid 案例2 通过jstack 排查死锁问题 #启动java代码 jstack 进…

【Linux权限】—— 于虚拟殿堂,轻拨密钥启华章

欢迎来到ZyyOvO的博客✨&#xff0c;一个关于探索技术的角落&#xff0c;记录学习的点滴&#x1f4d6;&#xff0c;分享实用的技巧&#x1f6e0;️&#xff0c;偶尔还有一些奇思妙想&#x1f4a1; 本文由ZyyOvO原创✍️&#xff0c;感谢支持❤️&#xff01;请尊重原创&#x1…

(2)SpringBoot自动装配原理简介

SpringBoot自动装配 这里写目录标题 SpringBoot自动装配启动器主程序自定义扫描包SpringBootApplicationSpringBootConfigurationEnableAutoConfigurationAutoConfigurationPackageImport({AutoConfigurationImportSelector.class})选择器AutoConfigurationEntrygetCandidateCo…

计算机网络 (60)蜂窝移动通信网

一、定义与原理 蜂窝移动通信网是指将一个服务区分为若干蜂窝状相邻小区并采用频率空间复用技术的移动通信网。其原理在于&#xff0c;将移动通信服务区划分成许多以正六边形为基本几何图形的覆盖区域&#xff0c;称为蜂窝小区。每个小区设置一个基站&#xff0c;负责本小区内移…

17.Word:李楠-学术期刊❗【29】

目录 题目​ NO1.2.3.4.5 NO6.7.8 NO9.10.11 NO12.13.14.15 NO16 题目 NO1.2.3.4.5 另存为手动/F12Fn光标来到开头位置处→插入→封面→选择花丝→根据样例图片&#xff0c;对应位置填入对应文字 (手动调整即可&#xff09;复制样式&#xff1a;开始→样式对话框→管理…