【C++入门到精通】C++ thread线程库 [ C++入门 ]
阅读导航
- 引言
- 一、thread类的简单介绍
- 二、thread类的用法
- 1. 创建线程
- 2. 使用 Lambda 表达式
- 3. 传递参数给线程
- 4. 线程的 join 和 detach
- 5. 检查线程是否可 join
- 6. 线程的 ID
- 7. 线程的移动语义
- 8. 线程的析构
- 🚨 注意事项
- 三、线程函数参数
- 温馨提示
引言
C++ thread线程库是C++11标准引入的一个强大工具,它提供了一种便捷的方式来创建和管理线程,使得并行编程变得更加容易和高效。这个库支持线程的创建、同步、互斥以及线程局部存储等功能。通过使用std::thread
类,开发者可以轻松地创建新的线程来执行任务,并使用join()
方法来等待线程完成。此外,线程库还包括了std::mutex
和std::lock_guard
等同步原语,以帮助管理线程间的资源访问,防止数据竞争和死锁。线程局部存储std::thread::id
和thread_local
关键字则允许线程拥有自己的局部数据,这在多线程环境中非常有用。总的来说,C++ thread线程库为C++开发者提供了一个功能全面、易于使用的多线程编程解决方案。让我们一起开始这段关于thread
线程库的学习之旅吧。
一、thread类的简单介绍
std::thread
类是C++11标准库中的一个核心组件,用于创建和管理独立的线程。它允许开发者通过传递一个函数或可调用对象来初始化线程,执行并行任务。线程对象的生命周期控制着线程的执行,而通过join()
和detach()
方法,可以控制线程的同步和分离。此外,std::thread
还提供了线程ID和状态检查功能,帮助开发者进行线程管理和异常处理,确保程序的稳定性和效率。
🚨注意:要使用线程库中的线程,必须包含<thread>头文件。线程类官方介绍文档
下面这个表格包含了 std::thread
类的构造函数、赋值运算符、比较运算符以及一些用于线程管理的成员函数。这些函数提供了创建、管理、比较和销毁线程的能力.
函数名 | 功能描述 |
---|---|
id get_id() | 返回线程的唯一标识符。 |
bool joinable() | 检查线程是否可 join,即是否还在运行。 |
void join() | 等待线程结束执行。 |
void detach() | 将线程与 std::thread 对象分离,使其在后台独立运行。 |
void swap(std::thread& other) | 与另一个 std::thread 对象交换线程。 |
thread::native_handle_type native_handle() | 返回线程的原生句柄,用于操作系统特定的线程操作。 |
bool operator==(const thread& other) const | 比较两个线程是否相同。 |
bool operator!=(const thread& other) const | 比较两个线程是否不同。 |
thread() noexcept | 默认构造函数,创建一个未关联线程的 std::thread 对象。 |
thread(nullptr_t) noexcept | 构造一个未关联线程的 std::thread 对象。 |
explicit thread(Callable&& func, Args&&… args) | 构造函数,创建一个线程并启动它来执行给定的可调用对象和参数。 |
thread(thread&& other) noexcept | 移动构造函数,获取另一个 std::thread 对象的所有权。 |
thread& operator=(thread&& other) noexcept | 移动赋值运算符,获取另一个 std::thread 对象的所有权。 |
~thread() | 析构函数,如果线程可 join,则会调用 join() ,否则调用 detach() 。 |
二、thread类的用法
std::thread
类是 C++ 标准库中用于线程创建和管理的类。以下是 std::thread
类的一些关键用法和示例:
1. 创建线程
要创建一个线程,你需要实例化 std::thread
对象并传递一个函数或可调用对象(如 lambda 表达式或函数对象)作为参数。
#include <iostream>
#include <thread>void threadFunction() {std::cout << "Hello from thread!" << std::endl;
}int main() {std::thread t(threadFunction);t.join(); // 等待线程结束return 0;
}
2. 使用 Lambda 表达式
Lambda 表达式提供了一种简洁的方式来定义匿名函数对象,非常适合用于线程。
#include <iostream>
#include <thread>int main() {std::thread t([]() {std::cout << "Hello from lambda thread!" << std::endl;});t.join();return 0;
}
3. 传递参数给线程
你可以将参数传递给线程函数。
void threadFunctionWithArgs(int x, double y) {std::cout << "x: " << x << ", y: " << y << std::endl;
}int main() {std::thread t(threadFunctionWithArgs, 10, 3.14);t.join();return 0;
}
4. 线程的 join 和 detach
join()
: 调用此方法会阻塞,直到线程结束执行。detach()
: 调用此方法会使线程在后台继续运行,而不受std::thread
对象的生命周期限制。
int main() {std::thread t([]() {// 线程执行的代码});t.detach(); // 线程现在在后台运行,不会等待它结束// 主线程继续执行,而 t 线程在后台运行return 0;
}
5. 检查线程是否可 join
在调用 join()
或 detach()
之前,可以使用 joinable()
检查线程是否还在运行。
int main() {std::thread t([]() {// 线程执行的代码});if (t.joinable()) {t.join(); // 线程还在运行,等待结束}return 0;
}
6. 线程的 ID
每个线程都有一个唯一的 ID,可以使用 get_id()
获取。
int main() {std::thread t([]() {std::cout << "Thread ID: " << std::this_thread::get_id() << std::endl;});t.get_id(); // 获取线程 IDt.join();return 0;
}
7. 线程的移动语义
std::thread
对象可以被移动,但不能被复制。这意味着你可以通过移动语义来转移线程的所有权。
int main() {std::thread t1([]() {std::cout << "Thread 1 running" << std::endl;});std::thread t2 = std::move(t1); // t1 的所有权转移给 t2t2.join(); // 等待线程结束return 0;
}
8. 线程的析构
当 std::thread
对象被销毁时,如果线程是可 join 的,那么 join()
会被自动调用。如果线程已经被分离,则不会有任何操作。
{std::thread t([]() {// 线程执行的代码});// t 在这里离开作用域,自动调用 join()
} // t 的析构函数被调用
🚨 注意事项
- 确保在
std::thread
对象生命周期结束前,线程已经被正确处理(join 或 detach)。 - 避免在线程函数中调用
std::exit()
或者抛出未捕获的异常,因为这可能会导致程序的不稳定。 - 使用互斥锁和条件变量来同步线程,避免数据竞争和死锁。
std::thread
提供了强大的工具来实现多线程编程,但也需要谨慎使用以确保程序的正确性和稳定性。
三、线程函数参数
线程函数的参数是以值拷贝的方式拷贝到线程栈空间中的,因此:即使线程参数为引用类型,在线程中修改后也不能修改外部实参,因为其实际引用的是线程栈中的拷贝,而不是外部实参。
#include <thread>void ThreadFunc1(int& x) {x += 10;
}void ThreadFunc2(int* x) {*x += 10;
}int main() {int a = 10;// 在线程函数中对a修改,不会影响外部实参,因为:线程函数参数虽然是引用方式,但其实际引用的是线程栈中的拷贝 std::thread t1(ThreadFunc1, a);t1.join(); // 如果想要通过形参改变外部实参时,必须借助std::ref()函数std::thread t2(ThreadFunc1, std::ref(a));t2.join(); // 等待线程执行完成// 地址的拷贝std::thread t3(ThreadFunc2, &a);t3.join(); // 等待线程执行完成 return 0;
}
温馨提示
感谢您对博主文章的关注与支持!另外,我计划在未来的更新中持续探讨与本文相关的内容,会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注博主的更新,不要错过任何精彩内容!
再次感谢您的支持和关注。期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!
相关文章:

【C++入门到精通】C++ thread线程库 [ C++入门 ]
阅读导航 引言一、thread类的简单介绍二、thread类的用法1. 创建线程2. 使用 Lambda 表达式3. 传递参数给线程4. 线程的 join 和 detach5. 检查线程是否可 join6. 线程的 ID7. 线程的移动语义8. 线程的析构🚨 注意事项 三、线程函数参数温馨提示 引言 C thread线程…...

CMakeFile.txt通过sysroot方式后生成makefile报错
报错信息如下: -- The C compiler identification is unknown -- The CXX compiler identification is unknown -- Check for working C compiler: /home/xj/asm/host/bin/aarch64-buildroot-linux-gnu-gcc -- Check for working C compiler: /home/xj/asm/host/bi…...

Python 将Word、Excel、PDF、PPT文档转为OFD文档
OFD(Open Fixed-layout Document )是我国自主制定的一种开放版式文件格式标准。OFD文档具有不易被篡改、格式独立、版式固定等特点,目前常用于政府公文、金融、电子发票等领域。 如果想要通过Python将Office文档(如Word、Excel或…...
【java11】java11新特性之局部变量类型推断升级
局部变量类型推断是java10开始新增的新特性,java11中对局部变量推断进行了升级,var支持添加注解的语法格式,Java10中是无法实现的,在Java11中加入了这样的语法。 Lambda中使用var修饰符 Java11允许在lambda表达式中使用var&…...

遥感卫星影像处理流程
当空中的遥感卫星获取了地球数字影像,并传回地面,是否工作就结束了?答案显然是否定的,相反,这正是遥感数字图像处理工作的开始。 遥感数字图像(Digital image,后简称“遥感影像”)是…...

【AR开发-开源框架】使用Sceneform-EQR快速开发AR应用,当前接入了AREngine、ORB-SLAM,可快速地适配不同的安卓设备
Sceneform-EQR Sceneform 概览 Sceneform是一个3D框架,具有基于物理的渲染器,针对移动设备进行了优化,使您可以轻松构建增强现实应用程序,而无需OpenGL。 借助 Sceneform,您可以轻松地在 AR 应用和非 AR 应用中渲染…...

学生信息管理系统C++
设计目的 使学生进一步理解和掌握课堂上所学的面向对象C编程知识,巩固和加深学生对C面向对象课程的基本知识的理解和掌握。掌握C面向对象编程和程序调试的基本技能,学会利用C语言进行基本的软件设计,着重提高运用C面向对象语言解决实际问题的…...
前端开发三大主流框架解析
Web前端三大主流框架分别是Angular、React和Vue.js。以下是《优联前端》关于这三个框架解析介绍: Angular: 来源与开发者:Angular是由Google开发的前端框架。功能特点:Angular是一个完整的框架,包括了数据绑定、组件化…...

【2.文件和目录相关(下)】
一、查看文件内容命令 1、cat 文件名:用于显示文件内容,比如 cat test.c。 (1)cat -b test.c 表示加行号显示文件内容。 (2)cat -s test.c 表示多个空行合并成一个空行显示。 2、nl 文件名:…...

【C语言】结构体与内存对齐
前言 在本篇博客,我将介绍结构体类型,结构体变量的创建和初始化,重点介绍结构中存在的内存对齐。 结构变量 结构是一些值的集合,这些值被称为成员变量。结构的每个成员可以是不同类型的变量。 在理解结构的时候,我们…...
【机器学习】之 kmean算法原理及实现
基本概念 K-Means 聚类算法的目标是将数据集分成 ( K ) 个簇,使得每个簇内的数据点尽可能相似,而簇与簇之间尽可能不同。这种相似度是通过计算数据点与簇中心的距离来衡量的。 算法步骤 选择簇的数量 ( K ):随机选择 ( K ) 个数据点作为初…...
国产高边驱动HD70202Q替换英飞凌BTS7040-2
高边驱动也称之为高边开关,主要用于车内负载的驱动与开关,并对负载进行保护和诊断。高边驱动以高可靠性、灵活性、低功耗以及小型轻量等特点,正逐渐替代传统的保险丝、继电器等方案。 RAMSUN提供的HD70202Q车规级双通道智能高边驱动的输入控…...

2024年06月在线IDE流行度最新排名
点击查看最新在线IDE流行度最新排名(每月更新) 2024年06月在线IDE流行度最新排名 TOP 在线IDE排名是通过分析在线ide名称在谷歌上被搜索的频率而创建的 在线IDE被搜索的次数越多,人们就会认为它越受欢迎。原始数据来自谷歌Trends 如果您相…...
顺序表和链表基础操作的复习
顺序表 #include<iostream> using namespace std; 静态 //#define MAX_SIZE 50 //typedef int ElemType; //typedef struct //{ // int length; // ElemType nums[MAX_SIZE]; //}Sqlist; //动态: #define Init_SIZE 50 typedef int ElemType; typedef struct {int lengt…...

[C#]winform部署官方yolov10目标检测的onnx模型
【框架地址】 https://github.com/THU-MIG/yolov10 【算法介绍】 今天为大家介绍的是 YOLOv10,这是由清华大学研究团队最新提出的,同样遵循 YOLO 系列设计原则,致力于打造实时端到端的高性能目标检测器。 方法 创新 双标签分配策略 众所…...

hmcode硬件编程1
在/home/golemon/hmcode/applications/sample/wifi-iot/app内创建文件夹。 这里创建了d_6_3文件夹 . ├── BUILD.gn ├── d_6_3 │ ├── BUILD.gn │ └── lab.c ├── demolink │ ├── BUILD.gn │ └── helloworld.c ├── iothardware │ ├── B…...
[C++][CMake] set_target_properties called with incorrect number of arguments
1 简介 这篇文章将探讨了在使用CMake构建C项目时,调用set_target_properties函数时参数数量不正确所引发的问题。 2 错误案例 以下为可能发生错误的案例 include_directories (${CMAKE_SOURCE_DIR}/common) find_package(Threads)add_library (libusbmuxd SHARE…...
AdamW算法
AdamW算法是优化算法Adam的一个变体,它在深度学习中广泛应用。AdamW的主要改进在于它正则化方法的改变,即通过权重衰减(weight decay)而不是L2正则化,来控制模型参数的大小,从而提升了训练的稳定性和效果。…...

【c++进阶(二)】STL之string类的模拟实现
💓博主CSDN主页:Am心若依旧💓 ⏩专栏分类c从入门到精通⏪ 🚚代码仓库:青酒余成🚚 🌹关注我🫵带你学习更多c 🔝🔝 1.前言 本章重点 本章主要介绍一些关键接口的模拟实现ÿ…...

PHPStudy(xp 小皮)V8.1.1 通过cmd进入MySQL命令行模式
PHPStudy是一个PHP开发环境集成包,可用在本地电脑或者服务器上,该程序包集成最新的PHP/MySql/Apache/Nginx/Redis/FTP/Composer,一次性安装,无须配置即可使用。MySQL MySQL是一个关系型数据库管理系统,由瑞典 MySQL A…...

idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
Qt 事件处理中 return 的深入解析
Qt 事件处理中 return 的深入解析 在 Qt 事件处理中,return 语句的使用是另一个关键概念,它与 event->accept()/event->ignore() 密切相关但作用不同。让我们详细分析一下它们之间的关系和工作原理。 核心区别:不同层级的事件处理 方…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...