c++ std::thread线程类

1. std::thread类

/*
源码来自vs2017
*/using _Thrd_id_t = unsigned int;
struct _Thrd_t { // thread identifier for Win32void* _Hnd; // Win32 HANDLE_Thrd_id_t _Id; //保存线程id
};class thread { // class for observing and managing threads
public:class id;using native_handle_type = void*;thread() noexcept : _Thr{} {}private:...template <class _Fn, class... _Args>void _Start(_Fn&& _Fx, _Args&&... _Ax) {...}public:template <class _Fn, class... _Args, enable_if_t<!is_same_v<_Remove_cvref_t<_Fn>, thread>, int> = 0>_NODISCARD_CTOR explicit thread(_Fn&& _Fx, _Args&&... _Ax) {_Start(_STD forward<_Fn>(_Fx), _STD forward<_Args>(_Ax)...);}thread(thread&& _Other) noexcept : _Thr(_STD exchange(_Other._Thr, {})) {}thread& operator=(thread&& _Other) noexcept {...}thread(const thread&) = delete;thread& operator=(const thread&) = delete;~thread() noexcept {...}void swap(thread& _Other) noexcept {...}//判断线程是否可以被join,实际判断线程ID是否为0_NODISCARD bool joinable() const noexcept {...}//等待线程void join() {...}//线程分离void detach() {...}//获取线程ID_NODISCARD id get_id() const noexcept;//获取win32句柄_NODISCARD native_handle_type native_handle() noexcept /* strengthened */ { // return Win32 HANDLE as void *return _Thr._Hnd;}//检测硬件并发特性_NODISCARD static unsigned int hardware_concurrency() noexcept {return _Thrd_hardware_concurrency();}private:_Thrd_t _Thr;
};

 常用的接口有: 构造函数, joinable(), join(),detach(),get_id();

2. std::thread 无参使用

void threadFunc() {  std::this_thread::sleep_for(std::chrono::seconds(5));std::cout << "thread ID: " << std::this_thread::get_id() << std::endl;
}int main() 
{std::thread myThread(threadFunc);cout << myThread.get_id() << endl;if (myThread.joinable()) {//myThread.detach(); 线程分离,只能看到 main ID 打印myThread.join(); //都能看见ID打印}return 0;
}

 

3. std::thread参数传递(避坑)

当线程传递参数时,需特别注意与detech()一起使用时出现的问题; 

3.1 传递临时对象作为线程参数

void threadFunc1(const int& i, char* buf)
{std::cout << "&i=" << &i << " &buf=" << (void *)buf << std::endl;&i = 0000023590C30A98 & buf = 00000037DD95FA58
}int main() 
{int val = 10;int &reVal = val;char buf[] = "this is test";std::thread myThread(threadFunc1, val,buf);cout << "main &val="  <<  &val << " &buf=" << &buf << endl;//main &val=00000037DD95FA14 &buf=00000037DD95FA58if (myThread.joinable()) {//myThread.join(); //没啥问题myThread.detach(); }return 0;
}

 当使用引用和指针作为线程参数传递时, 经过打印知 i实际为值传递, 而buf与main地址相同;

那么就可能存在detach()时,主线程已经跑完且buf地址已经失效,而线程中可能还在使用该地址;

避坑:

// const string& buf建议使用引用,省一次构造
void threadFunc2(const int i, const string& buf)
{std::cout << i << " "<< buf.c_str() << std::endl;
}int main() 
{int val = 10;int &reVal = val;char buf[] = "this is test";//直接将其转为string对象,且要保证在main中就转成功;//即使这里是引用, 也能够保证两者地址不一样;std::thread myThread(threadFunc2, val,string(buf));if (myThread.joinable()) {//myThread.join(); //没啥问题myThread.detach(); }return 0;
}

3.2 传递类对象作为线程参数

//不加&多产生一次拷贝构造,建议都加上;
void threadFunc3(const A &buf)
{std::cout << buf.m_i << endl;
}int main() 
{A objA(10);std::thread myThread(threadFunc3, objA);//就想传递引用呢, 加上std::ref即可//std::thread myThread(threadFunc3, std::ref(objA));if (myThread.joinable()) {myThread.join(); }return 0;
}

3.3 传递智能指针作为线程参数

void threadFunc4(std::unique_ptr<int> ptr)
{
}int main() 
{std::unique_ptr<int> myPtr(new int(10));//传递后myPtr指向空了 不能使用detech,因为主线程先执行完,myPtr指向的对象被释放了;std::thread myThread(threadFunc4, std::move(myPtr)); // 移动智能指针到线程if (myThread.joinable()) {myThread.join(); //myThread.detach();//一定不能是detach}return 0;
}

3.4 传递成员函数指针作为线程参数

class A
{
public:int m_i;//类型转换构造函数,可以把一个Int转成类对象;A(int a) :m_i(a) { cout << "构造" << this << "thread id= " << std::this_thread::get_id() << endl; }A(const A& a) :m_i(a.m_i) { cout << this << "thread id= " << std::this_thread::get_id() << "拷贝构造" << endl; }~A() { cout << "析构" << this << "thread id= " << std::this_thread::get_id() << endl; }void thread_work(int num){cout << "thread_work" << endl;}
};int main() 
{A myobj(10);std::thread myThread(&A::thread_work, myobj, 15);//有拷贝构造产生//std::thread myThread(&A::thread_work, std::ref(myobj), 15);//没有拷贝构造,不能用detach();if (myThread.joinable()) {myThread.join(); //myThread.detach();//一定不能是detach}return 0;
}

 

4. 扩展:std::this_thread类

namespace this_thread {thread::id get_id() noexcept;inline void yield() noexcept;void sleep_until(const xtime* _Abs_time) ;void sleep_for(const chrono::duration<_Rep, _Period>& _Rel_time) 
};

4.1 get_id()

作用同 std::thread::get_id(); 获取线程ID值;

void threadFunc3()
{std::cout << std::this_thread::get_id() << endl;//32320
}int main() 
{std::thread myThread(threadFunc3);std::cout << myThread.get_id() << std::endl;//32320if (myThread.joinable()) {myThread.join(); }return 0;
}

4.2 yield

yield参考 

4.3  sleep_until

阻塞当前正在执行的线程直到sleep_time溢出。 参考

 4.4 sleep_for

延时一段时间,支持ns到hour;

auto start = std::chrono::high_resolution_clock::now();std::this_thread::sleep_for(std::chrono::nanoseconds(1000));//1000ns
std::this_thread::sleep_for(std::chrono::microseconds(1000));//1000us
std::this_thread::sleep_for(std::chrono::milliseconds(1000));//1000ms
std::this_thread::sleep_for(std::chrono::seconds(5));//5sstd::chrono::duration<double, std::milli> elapsed = std::chrono::high_resolution_clock::now() - start;std::cout << elapsed.count() << endl;

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

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

相关文章

Linux内核学习笔记——ACPI命名空间

所有定义块都加载到单个命名空间中。命名空间 是由名称和路径标识的对象层次结构。 以下命名约定适用于 ACPI 中的对象名称 命名空间&#xff1a; 所有名称的长度均为 32 位。 名称的第一个字节必须是“A”-“Z”、“_”之一。 名称的每个剩余字节必须是“A”-“Z”、“0”之…

【移动端开发】鸿蒙系统开发入门:代码示例与详解

一、引言 随着华为鸿蒙系统的日益成熟&#xff0c;越来越多的开发者开始关注这一新兴的操作平台。本文旨在为初学者提供一份详尽的鸿蒙系统开发入门指南&#xff0c;通过具体的代码示例&#xff0c;引导大家逐步掌握鸿蒙开发的基本概念和技术。 二、鸿蒙系统开发基础 鸿蒙系…

Mysql-InnoDB数据页结构

一、页结构说明 大致分7部分 二、记录在页中的存储 2.1 页面记录内存结构 行格式 存储到 User Records 部分&#xff0c;每当我们插入一条记录&#xff0c;都会从 Free Space 部分申请一个记录大小的空间划分到 User Records 部分 &#xff0c;用完则申请新的页&#xff1b; …

open cv学习 (十一)视频处理

视频处理 demo1 import cv2 # 打开笔记本内置摄像头 capture cv2.VideoCapture(0) # 笔记本内置摄像头被打开 while capture.isOpened():# 从摄像头中实时读取视频retval, image capture.read()# 在窗口中实时显示读取到的视频cv2.imshow("Video", image)# 等到用…

《React.js手把手教程:从初学者到实战高手》- 关于React.js

最近公司倒闭了。目前这个大环境&#xff0c;不知何时能找到下一家。但人不能闲着&#xff0c;总得给自己找点事做。 其实很早之前就想写本书了&#xff0c;但苦于一直没有闲情。既然现在有点时间&#xff0c;那就开始动手吧。 刚开始是想写有关React Native的&#xff0c;但…

【MySQL系列】Select语句单表查询详解(一)

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

【unity数据持久化】XML数据管理器知识点

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;Uni…

计算工具类

计算工具类: package com.test.common.utils;import org.springframework.lang.NonNull; import org.springframework.stereotype.Component;import java.time.Duration; import java.util.Date; import java.util.Objects;/*** 计算工具类*/ Component public class Calculat…

Wireshark数据抓包分析之互联网协议(IP协议)

一、实验目的&#xff1a; 通过wireshark抓包分析IP协议的具体内容 二、预备知识&#xff1a; 1.IP地址存在的意义&#xff0c;就是为了弥补mac地址的不足&#xff0c;用于区分不同的网络 2.还有一些ip协议、ip数据包这些东西 三、网络拓扑 四、实验过程&#xff1a; part1&…

如何在 Kubernetes 中借助 Service 实现灰度发布和蓝绿发布

前言 部署在 Kubernetes 集群中的应用&#xff0c;在升级发布时可能会存在的问题&#xff1a; 1&#xff0c;由于 Kuberneter 底层 Pod 容器生命周期与网络组件生命周期是异步管理的&#xff0c;在升级时如果没有处理好应用优雅退出的问题&#xff0c;就很容易导致 http 访问请…

四川玖璨电子商务有限公司:怎么拉升抖店体验分

抖音是中国最受欢迎的短视频分享平台之一&#xff0c;而在抖音上开设自己的抖店成为许多电商从业者的选择。为了提高抖店的曝光度和用户体验&#xff0c;抖店体验分成为了一个重要的指标。在本文中&#xff0c;小编将从两个方面来讨论怎么拉升抖店体验分&#xff0c;包括影响因…

Flink的Standalone部署实战

在Flink是通用的框架&#xff0c;以混合和匹配的方式支持部署不同场景&#xff0c;而Standalone单机部署方便快速部署&#xff0c;记录本地部署过程&#xff0c;方便备查。 环境要求 1&#xff09;JDK1.8及以上 2&#xff09;flink-1.14.3 3&#xff09;CentOS7 Flink相关信…

第 7 章 排序算法(4)(插入排序)

7.7插入排序 7.7.1插入排序法介绍: 插入式排序属于内部排序法&#xff0c;是对于欲排序的元素以插入的方式找寻该元素的适当位置&#xff0c;以达到排序的目的。 7.7.2插入排序法思想: 插入排序&#xff08;Insertion Sorting&#xff09;的基本思想是&#xff1a;把n个待排…

app版本号比对

package com.zyy.user.api.helper;import com.zyy.framework.model.dto.result.ResultEnum; import com.zyy.framework.model.exception.BusinessException; import lombok.Builder; import lombok.Data;import javax.validation.constraints.NotNull;/*** APP版本比较工具*/ p…

点云平面拟合和球面拟合

一、介绍 In this tutorial we learn how to use a RandomSampleConsensus with a plane model to obtain the cloud fitting to this model. 二、代码 #include <iostream> #include <thread> #include <pcl/point_types.h> #include <pcl/common/io.…

Android GreenDao数据库升级(附Demo)

前言 大家好久不见&#xff0c;一转眼马上八月份下旬了&#xff0c;最近由于工作比较忙&#xff0c;没时间给大家更新博文。百忙之中抽出时间&#xff0c;给大家来更新一篇关于GreenDao3数据库的升级。 关于GreenDao的详细介绍以及一些逻辑性的增、删、改、查等&#xff0c;可以…

Nevron Open Vision for .NET Crack

Nevron Open Vision for .NET Crack NET Vision是一个用于生成具有数据可视化功能的强大数据表示应用程序的包。该套件具有用于.NET的Nevron Chart、用于.NET的Nevron Diagram和用于.NET的Nevron User Interface。精心设计的对象模型、许多功能和卓越的演示使复杂数据的可视化变…

【Git起步】初次安装和配置

1.什么是版本控制 版本控制系统&#xff08;VCS&#xff09;是一种记录文件内容变化以便将来查阅特定版本修订情况的系统。 使用版本控制系统在出错时、需要时可以回溯。 2.Git简介 Git是一个分布式版本控制系统&#xff0c;用于跟踪和管理代码的变更历史。 它允许开发者在…

git操作:将一个仓库的分支提交到另外一个仓库分支

这个操作&#xff0c;一般是同步不同网站的同个仓库&#xff0c;比如说gitee 和github。某个网站更新了&#xff0c;你想同步他的分支过来。然后基于分支开发或者其它。 操作步骤 1.本地先clone 你自己的仓库。也就是要push 分支的仓库。比如A仓库&#xff0c;把B仓库分支&am…

分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测

分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测 目录 分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测分类效果基本介绍程序设计参考资料 分类效果 基本介绍 分类预测 | MATLAB实现S4VM半监督支持向量机二分类预测 程序设计 完整源码和数据获取方式&#xff1a; …