【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::mutexstd::lock_guard等同步原语,以帮助管理线程间的资源访问,防止数据竞争和死锁。线程局部存储std::thread::idthread_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++、算法和编程的奥秘。祝您生活愉快,排便顺畅!

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

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

相关文章

实现流程化办公,可以相信拖拽表单设计器!

当前&#xff0c;竞争压力越来越大&#xff0c;利用什么样优良的办公软件实现流程化办公&#xff1f;可以一起来了解低代码技术平台、拖拽表单设计器的优势特点&#xff0c;看看它们是如何助力企业降本、增效、提质的。低代码技术平台的优势特点多&#xff0c;可以助力企业用拖…

轻松实现微信内下载,Xinstall让你的App推广更高效!

在微信中推广App&#xff0c;你是否遇到过这样的困扰&#xff1a;推广链接被微信拦截&#xff0c;用户需要手动复制链接到浏览器才能下载&#xff0c;大大降低了安装率&#xff1f;今天&#xff0c;我们要介绍的Xinstall&#xff0c;就是一款能够解决这一痛点的神器&#xff01…

2.2 OpenCV随手简记(三)

图像的阈值处理定义 &#xff1a;将图像转化为二值图像&#xff08;黑白图&#xff09;, 也可以用于彩色图形&#xff0c;达到夸张的效果 目的&#xff1a;是用来提取图像中的目标物体&#xff0c;将背景和噪声区分开&#xff08;可以近似的认为除了目标全是噪声&#xff09;。…

GSEA的算法只考虑排序吗

其实这个问题很好回答&#xff0c;只需要运行如下代码&#xff0c;如下的基因列表是顺序是完全相同&#xff0c;并且我们只是做了最基础的变换 library(clusterProfiler) library(org.Hs.eg.db)data(geneList, package"DOSE")ego1 <- gseGO(geneList geneLi…

【iOS】UI学习(二)

UI学习&#xff08;二&#xff09; 进度条和滑动条步进器与分栏控件警告对话框和提示等待器UITextFieldUITextField控件UITextFieldDelegate协议 UIScrollView布局子视图手动布局子视图自动布局子视图 进度条和滑动条 下面通过一个程序来讲解该内容&#xff1a; #import <…

Django 里的增删改查

下面是步骤 先更新 urls.py 来添加新的url from django.contrib import admin from django.urls import path from app01 import viewsurlpatterns [path(demo/, views.demo), ]在 models.py 里创建表 from django.db import models# Create your models here. class UserI…

力扣 226. 翻转二叉树

给你一棵二叉树的根节点 root &#xff0c;翻转这棵二叉树&#xff0c;并返回其根节点。 /*** Definition for a binary tree node.* struct TreeNode {* int val;* struct TreeNode *left;* struct TreeNode *right;* };*/ struct TreeNode* invertTree(struct Tr…

[leetcode hot150]第五十七题,插入区间

题目&#xff1a; 给你一个 无重叠的 &#xff0c;按照区间起始端点排序的区间列表 intervals&#xff0c;其中 intervals[i] [starti, endi] 表示第 i 个区间的开始和结束&#xff0c;并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval [start, end] 表示…

62. UE5 RPG 近战攻击获取敌人并造成伤害

在上一篇&#xff0c;我们实现了通过AI行为树控制战士敌人靠近攻击目标触发近战攻击技能&#xff0c;并在蒙太奇动画中触发事件激活攻击的那一刻的伤害判断&#xff0c;在攻击时&#xff0c;我们绘制了一个测试球体&#xff0c;用于伤害范围。 在之前实现的火球术中&#xff0c…

HBuilderX打包uni-app项目成安卓app

目录 1、下载Android 离线SDK 2、Android Studio导入工程 3、生成签名 3.1、进入到jdk bin目录下&#xff0c;输入cmd执行命令keytool -genkey -alias wxsalias -keyalg RSA -keysize 2048 -validity 36500 -keystore wxs.keystore 生成签名 3.2、查看签名密钥keytool -lis…

Simulink从0搭建模型08-P9 While If SwitchCase模块的使用的使用

Simulink从0搭建模型08-P9 While & If & SwitchCase模块的使用的使用 今日学习内容1. While1.1. While Iterator Subsystem模块1.2. 样例11.3. 样例2 2. If2.1. if模块If Action Subsystem模块&#xff08;action) 3. Switch3.1. Switch Case模块3.2. If Action Subsys…

Java实战:文本文件复制

任务目标 本实战任务的目标是创建一个Java程序&#xff0c;用于复制指定的文本文件到另一个位置&#xff0c;并在控制台中显示复制结果。 任务步骤 创建源文件&#xff1a;在指定的路径D:\love.txt创建源文件。创建文件复制类&#xff1a;在net.huawei.student.test包中创建…

成功解决“ModuleNotFoundError: No Module Named Pycocotools”错误的全面指南

成功解决“ModuleNotFoundError: No Module Named Pycocotools”错误的全面指南 在Python的数据科学、计算机视觉和机器学习项目中&#xff0c;经常需要用到各种工具和库来加速开发过程。其中&#xff0c;pycocotools 是一个专门用于处理 COCO 数据集的库&#xff0c;它提供了多…

代理IP如何提高网站的SEO排名

目录 一、代理IP的作用 二、使用代理IP提高SEO排名的几种常见方法 1. 采集数据 2. 提交网站 3. 模拟用户行为 4. 搜索引擎优化 三、合理使用代理IP的注意事项 四、代码示例 总结 代理IP是一种可以隐藏真实IP地址的技术&#xff0c;通过使用代理IP&#xff0c;可以实现…

最大的游戏交流社区Steam服务器意外宕机 玩家服务受影响

易采游戏网6月3日消息&#xff1a;众多Steam游戏玩家报告称&#xff0c;他们无法访问Steam平台上的个人资料、好友列表和社区市场等服务。同时&#xff0c;社区的讨论功能也无法正常使用。经过第三方网站SteamDB的确认&#xff0c;&#xff0c;这一现象是由于Steam社区服务器突…

新奇css模板

引言 (csscoco.com)https://csscoco.com/inspiration/#/./init

ardupilot开发 --- 机载计算机-软件方案 篇

马儿跑马儿不吃草 0. 概述APSyncBlueOSDroneKitFlytOSMaverickROSRpanion-server结论 0. 概述 The Companion Computer software refers to the programs and tools that run on the Companion Computer. They will take in MAVLink telemetry from the Flight Controller and…

Swift 中 @preconcurrency 修饰符使用浅谈

概述 Swift 6.0 与我们越来越近了&#xff0c;如何将旧范儿的并发代码装换为严格遵守 Swift 6.0 并发模型&#xff08; Strict Concurrency&#xff09;的新代码&#xff0c;这往往使得秃头码农们又要多抓掉几根头发了。 所以&#xff0c;为了最大限度的保持新旧两个并发世界暂…

模拟人为操作并获取数据

问题 假设需要获取一个微信公众号h5应用的某些数据&#xff0c;而这个应用存在如下一些反爬措施&#xff0c;从而决定了获取数据的方式。 每一个操作都有类似埋点行为&#xff0c;这样即可收集每个用户的操作轨迹。通过轨迹正常与否&#xff0c;很容易判断一个用户是否在恶意获…

【Spring Cloud Alibaba】开源组件Nacos及安装与配置

目录 什么是NacosNacos的关键特性服务发现和服务健康监测动态配置服务动态 DNS 服务服务及其元数据管理 Nacos的架构Nacos的用户Nacos的安装预备环境准备安装方式有两种&#xff1a;源码安装和下载编译好的安装包Nacos 支持三种部署模式&#xff0c;分别是单机、集群和多集群。…