【C++】详解std::thread

2023年9月10日,周日下午开始

2023年9月10日,周日晚上23:35完成

虽然这篇博客我今天花了很多时间去写,但是我对std::thread有了一个完整的认识

不过有些内容还没完善,以后有空再更新....


目录

  • 头文件
  • 类的成员
  • 类型
  • 方法
  • (constructor)
  • terminate called without an active exception是什么?
  • operation=
  • get_id
  • joinable
  • join
  • detach
  • native_handle
  • swap
  • hardware_concurrency

头文件

#include<thread>

类的成员

类型

id 线程ID(公共成员类型)

native_handle_type 本地句柄类型(公共成员类型)

方法

(constructor) 构造线程(公共成员函数)

(destructor) 线程析构函数(公共成员函数)

operator= 移动赋值线程(公共成员函数)

get_id 获取线程ID(公共成员函数)

joinable 检查是否可加入(公共成员函数)

join 加入线程(公共成员函数)

detach 分离线程(公共成员函数)

swap 交换线程(公共成员函数)

native_handle 获取本地句柄(公共成员函数)

hardware_concurrency [static] 检测硬件并发性(公共静态成员函数)

(constructor)

该构造函数用来创建线程,并执行传入的函数

#include <iostream>      
#include<thread> 
void func() 
{std::cout << "func executes!" << std::endl;
}int main() 
{std::thread t1(func);return 0;
}

这里的“terminate called without an active exception”暂时不用管

terminate called without an active exception是什么?

"terminate called without an active exception"是一个C++程序运行时可能遇到的异常信息。

它表示程序在没有活动异常的情况下被终止了。

这个异常通常发生在以下情况下:

  1. 程序主动调用了std::terminate()函数来终止程序的执行。这可能是因为程序遇到了无法处理的错误或异常情况。
  2. 程序由于未捕获的异常而终止。当程序抛出一个未捕获的异常时,如果没有其他活动的异常,系统会调用std::terminate()来终止程序。
  3. 程序由于某些特定的终止条件而被操作系统或其他外部因素终止。例如,操作系统可能会根据内存使用情况或其他资源限制来终止程序。

operation=

在C++中,std::thread类提供了operator=运算符重载函数,用于将一个线程对象赋值给另一个线程对象。使用operator=可以将一个线程对象的控制转移到另一个线程对象,从而实现线程的交换或转移。这意味着调用operator=后,原线程对象将结束执行,而新线程对象将开始执行之前正在执行的代码。

get_id

该方法用来获取线程ID

#include <iostream>      
#include<thread> 
void func() 
{std::cout <<"func executes!" << std::endl;
}int main() 
{std::thread t1(func);std::cout<<"ID of thread t1 is "<<t1.get_id()<<std::endl;return 0;
}

可以看到线程ID为2

joinable

什么是join呢?join是什么意思?

在线程中,join指的是等待一个线程执行完毕并返回结果后再继续执行主线程。当主线程调用子线程的join方法时,主线程会阻塞并等待子线程执行完成。这样可以确保所有线程按照预期的顺序执行,并且最后的结果是正确的。

那不用join会发生什么事情呢?

主线程不会等待子线程完成,这样有可能子线程还没执行完主线程就结束了。

#include <iostream>      
#include<thread> 
void func() 
{std::cout <<"func executes!" << std::endl;
}int main() 
{std::thread t1(func);std::cout<<"ID of thread t1 is "<<t1.get_id()<<std::endl;if(t1.joinable())std::cout<<"joinable: ture"<<std::endl;elsestd::cout<<"joinable: false"<<std::endl;return 0;
}

join

上面已经说过,所以不再赘述

#include <iostream>      
#include<thread> 
void func() 
{std::cout <<"func executes!" << std::endl;
}int main() 
{std::thread t1(func);std::cout<<"ID of thread t1 is "<<t1.get_id()<<std::endl;if(t1.joinable())std::cout<<"joinable: ture"<<std::endl;elsestd::cout<<"joinable: false"<<std::endl;t1.join();return 0;
}

值得注意的是,没有了“terminate called without an active exception”

detach

什么是detach呢?detach是什么意思?

分离线程的主要目的是允许主线程在子线程执行一些耗时的操作时继续执行其他任务。通过分离线程,主线程可以避免被阻塞,从而提高程序的整体效率。

使用detach和不使用join有什么区别?

目前我还没搞懂....以后弄懂了再更新

#include <iostream>      
#include<thread> 
void func() 
{for(int i=0;i<10000;i++){//让线程休眠1秒std::this_thread::sleep_for(std::chrono::seconds(1));std::cout <<"func executes!" << std::endl;}
}int main() 
{std::thread t1(func);t1.detach();//让主线程给子线程足够的执行时间for(int i=0;i<10000;i++)std::this_thread::sleep_for(std::chrono::seconds(1);return 0;
}

native_handle

C++标准库中的native_handle是一个低级接口,可以获取底层操作系统的句柄(handle)。

native_handle主要用于一些需要直接与操作系统交互的低级场景。

swap

swap()函数的作用是将两个线程对象的控制转移到彼此,从而实现线程的交换。这意味着调用swap()后,两个线程将开始执行对方之前正在执行的代码。

#include <iostream>
#include <thread>void threadFunction1() {// 线程1的代码for(int i=0;i<10000;i++){//让线程休眠1秒std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Thread 1 is running." << std::endl;}}void threadFunction2() {// 线程2的代码for(int i=0;i<10000;i++){//让线程休眠1秒std::this_thread::sleep_for(std::chrono::seconds(1));std::cout << "Thread 2 is running." << std::endl;}
}int main() {std::thread t1(threadFunction1);  // 创建线程1std::thread t2(threadFunction2);  // 创建线程2t1.swap(t2);  // 交换线程1和线程2的状态t1.join();  // 等待线程1结束t2.join();  // 等待线程2结束return 0;
}

hardware_concurrency

在C++中,hardware_concurrency是一个用于确定系统上可用的处理器核心数量的函数。它返回一个整数值,表示可以并行执行的最大线程数。通常,hardware_concurrency()函数返回的值取决于底层操作系统和硬件平台。

#include <iostream>
#include <thread>int main() {unsigned int numThreads = std::thread::hardware_concurrency();std::cout << "Number of available processor cores: " << numThreads << std::endl;return 0;
}

可以看到我的最大并行线程数是8,这是由我电脑的CPU决定的。

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

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

相关文章

LVS DR模式负载均衡群集部署

目录 1 LVS-DR 模式的特点 1.1 数据包流向分析 1.2 DR 模式的特点 2 DR模式 LVS负载均衡群集部署 2.1 配置负载调度器 2.1.1 配置虚拟 IP 地址 2.1.2 调整 proc 响应参数 2.1.3 配置负载分配策略 2.2 部署共享存储 2.3 配置节点服务器 2.3.1 配置虚拟 IP 地址 2.3.2…

iOS IdiotAVplayer实现视频分片缓存

文章目录 IdiotAVplayer 实现视频切片缓存一 iOS视频边下边播原理一 分片下载的实现1 分片下载的思路2 IdiotAVplayer 实现架构 三 IdiotAVplayer 代码解析IdiotPlayerIdiotResourceLoaderIdiotDownLoader IdiotAVplayer 实现视频切片缓存 一 iOS视频边下边播原理 初始化AVUR…

自动化运维——ansible (五十二) (01)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 一、概述 1.1 为什么要用自动化运维软件 1.2 自动化运维 1.3 自动化运维要注意的方面 1.4 自动化运维主要关注的方面 1.5 常见的开源自动化运维软件 1.6 自动化运维软件…

K8S:kubectl陈述式及声明式资源管理

文章目录 一.陈述式资源管理方法1.陈述式资源管理概念2.基本信息查看&#xff08;1&#xff09;查看版本信息&#xff08;2&#xff09;查看资源对象简写&#xff08;3&#xff09;查看集群信息&#xff08;4&#xff09;配置kubectl自动补全&#xff08;5&#xff09;node节点…

外传-Midjourney的局部重绘功能

今天在抄袭。。。啊不&#xff0c;借鉴 midjourney 官网教程的时候&#xff0c;发现多了一个 局部重绘的功能&#xff0c;意外发觉还不错&#xff0c;分享一下用法。 先给大家说一下&#xff0c;我这段时间都在学习 SD&#xff0c;局部重绘是基操&#xff0c;而 MJ 一直是次次…

为什么要使用设计模式,以及使用设计模式的好处

在软件开发中&#xff0c;衡量软件质量只要包含如下指标&#xff1a; 正确性可维护性可读性可扩展性简洁性可测试性健壮性灵活性可复用性 然而&#xff0c;对于一些刚入行的新程序员来说&#xff0c;往往会注意不到上面这些问题&#xff0c;从而产生了一些让人头皮发麻的烂代…

【动态规划刷题 13】最长递增子序列 摆动序列

300. 最长递增子序列 链接: 300. 最长递增子序列 1.状态表示* dp[i] 表⽰&#xff1a;以 i 位置元素为结尾的「所有⼦序列」中&#xff0c;最⻓递增⼦序列的⻓度。 2.状态转移方程 对于 dp[i] &#xff0c;我们可以根据「⼦序列的构成⽅式」&#xff0c;进⾏分类讨论&#…

生成树协议 STP(spanning-tree protocol)

一、STP作用 1、消除环路&#xff1a;通过阻断冗余链路来消除网络中可能存在的环路。 2、链路备份&#xff1a;当活动路径发生故障时&#xff0c;激活备份链路&#xff0c;及时恢复网络连通性。 二、STP选举机制 1、目的&#xff1a;找到阻塞的端口 2、STP交换机的角色&am…

MAC M1芯片安装mounty读写移动硬盘中的文件

因为移动硬盘中的文件是微软公司NTFS格式&#xff0c;MAC只支持自己的APFS或者HFS&#xff0c;与微软的NTFS不兼容&#xff0c;所以需要第三方的软件来支持读写硬盘中的文件&#xff0c;经过一上午的折腾&#xff0c;最终选择安装mounty这个免费的第三方软件 工具网址连接&am…

YOLO目标检测——棉花病虫害数据集+已标注txt格式标签下载分享

实际项目应用&#xff1a;目标检测棉花病虫害数据集的应用场景涵盖了棉花病虫害的识别与监测、研究与防治策略制定、农业智能决策支持以及农业教育和培训等领域。这些应用场景可以帮助农业从业者更好地管理棉花病虫害&#xff0c;提高棉花产量和质量&#xff0c;推动农业的可持…

线性代数的本质(二)

文章目录 线性变换与矩阵线性变换与二阶方阵常见的线性变换复合变换与矩阵乘法矩阵的定义列空间与基矩阵的秩逆变换与逆矩阵 线性变换与矩阵 线性变换与二阶方阵 本节从二维平面出发学习线性代数。通常选用平面坐标系 O x y Oxy Oxy &#xff0c;基向量为 i , j \mathbf i,…

指针进阶(一)

指针进阶 1. 字符指针面试题 2. 指针数组3. 数组指针3.1 数组指针的定义3.2 &数组名VS数组名 3.3 数组指针的使用4. 数组传参和指针传参4.1 一维数组传参4.2 二维数组传参4.3 一级指针传参4.4 二级指针传参 前言 指针的主题&#xff0c;我们在初级阶段的《指针》章节已经接…

用滑动条做调色板---cv2.getTrackbarPos(),cv2.creatTrackbar()

滑动轨迹栏作调色板 cv.createTrackbar(‘R’, ‘image’, 0, 255, nothing) 参数&#xff1a;哪个滑动轨迹栏&#xff0c;哪个窗口&#xff0c;最小值&#xff0c;最大值&#xff0c;回调函数 cv.getTrackbarPos(‘R’, ‘image’) 参数&#xff1a;轨迹栏名&#xff0c;窗口…

Nodejs 第十五章(child_process)

child_process 子进程 子进程是Nodejs核心API&#xff0c;如果你会shell命令&#xff0c;他会有非常大的帮助&#xff0c;或者你喜欢编写前端工程化工具之类的&#xff0c;他也有很大的用处&#xff0c;以及处理CPU密集型应用。 创建子进程 Nodejs创建子进程共有7个API Sync…

controller接口上带@PreAuthorize的注解如何访问 (postman请求示例)

1. 访问接口 /*** 查询时段列表*/RateLimiter(time 10,count 10)ApiOperation("查询时段列表")PreAuthorize("ss.hasPermi(ls/sy:time:list)")GetMapping("/list")public TableDataInfo list(LsTime lsTime){startPage();List<LsTime> l…

【实践篇】Redis最强Java客户端(四)之Ression分布式集合使用指南

文章目录 0. 前言1.Ression分布式集合1.1 分布式列表1.1.1 使用场景和实现原理&#xff1a;1.1.2 基本概念和使用方法&#xff1a; 1.2 分布式集合1.2.1 使用场景和实现原理&#xff1a;1.2.2 基本概念和使用方法&#xff1a; 1.3 分布式映射1.3.1 使用场景和实现原理&#xff…

rv1126之isp黑电平(BLC)校准!

前言&#xff1a; 大家好&#xff0c;今天我们继续来讲解isp第二期内容&#xff0c;这期内容主要分三个部分&#xff1a; 1、tunning的工作流程 2、利用RKISP2.x_Tuner来创建tunning工程&#xff0c;并连接上rv1126开发板进行抓图 3、BLC(黑电平校准)的原理和校准方法以及实战…

Mojo安装使用初体验

一个声称比python块68000倍的语言 蹭个热度&#xff0c;安装试试 系统配置要求&#xff1a; 不支持Windows系统 配置要求: 系统&#xff1a;Ubuntu 20.04/22.04 LTSCPU&#xff1a;x86-64 CPU (with SSE4.2 or newer)内存&#xff1a;8 GiB memoryPython 3.8 - 3.10g or cla…

tcp连接+套接字编程

tcp头部 tcp端口号 TCP的连接是需要四个要素确定唯一一个连接&#xff1a;&#xff08;源IP&#xff0c;源端口号&#xff09; &#xff08;目地IP&#xff0c;目的端口号&#xff09; 所以TCP首部预留了两个16位作为端口号的存储&#xff0c;而IP地址由上一层IP协议负责传递 源…

idea的GsonFormatPlus插件教程

1 安装 插件 打开idea, File—>Setting—>Plugins,搜索 GsonFormatPlus 直接安装 2 json 转化为 实体类 2.1 新建一个类 2.2 点击右键 2.4 点击Format 生成注释