C++并发编程 - 线程管理

目录

等待线程的完成

传递参数

属性API

Reference


我们的std::thread对象就是在创建的时候方才执行函数,而不是使用某一个类似于run的API执行。这使得我们启动一个线程的方式变得很简单:

void task(void); // A demo
std::thread(task);

我们这样就派生出了一个执行流task。

出于C++语法解析的原因,有的时候我们会遇上定义-声明混淆的问题。比如说假使我们传递了一个自己定义的仿函数:

struct MyTask()
{
    void operator()(){
        do_one_thing(); // Decleared anyhow!
    }
    
    void do_one_thing(){/* ... */}
}
​
int main()
{
    MyTask t;
    std::thread task(t());
}

这里会被认为是声明了一个带有一个参数,返回值是std::thread的名称是task的函数。所以一个比较号的回避办法是:

显式告知我们调用的是std::thread的构造函数:

std::thread task( (t()) );

或者是使用统一大括号法:

std::thread task{ t() };

原书(《C++并发编程》)还提到了使用lambda,不失为一种方法,但是总有种脱裤子放屁的美感:

std::thread task([](){
    t(); // 或者把里头的东西展开写了    
})

必须值得注意的是,我们更多时候可能使用的是带有参数的函数,这也就意味着,如果这些参数是引用形式进行传递的,势必要保证这些参数是有效的!

struct MyFunc
{
    int& f;
    func(int& _i):f(_i){}
    void operator()(){
        for(int i = 0; i < 100000000; i++)
            do_someThing(f); // 极有可能会崩溃
    }   
}
​
void shitBro(){
    int some_local_st = 0;
    MyFunc f(some_local_st);
    std::thread t(MyFunc);
    t.detach(); // 这里表示的是脱离主线程称为一个后台线程
                // 结果可想而知,在这里函数出去,我们的对象引用这里就会失效!
}

等待线程的完成

一个线程结束他的作用域的时候,如果我们不指定线程的处理后事,程序可能会抛出一个异常来!所以,想要让一个线程结束作用域时仍然可以存在,只能两种选择

等待线程执行完毕(也就是std::thread的join方法)

脱离主线程成为后台进程(也就是std::thread的detach方法)

当然,还有一种办法就是将std::thread封装,我们实现自己默认行为的std::thread

#include <iostream>
#include <type_traits>
#include <thread>
​
class MyThread
{
    std::thread _thread;
public:
    MyThread() = delete;
    template<typename Callable, typename... Args>
    MyThread(Callable&& c, Args... a)
    {
        static_assert(std::is_invocable_v<Callable, Args...>, "Is not Invookable! Check Params");
        _thread = std::move(std::thread(std::forward<Callable>(c), std::forward<Args>(a)...));
    }
​
    ~MyThread()
    {
        if(_thread.joinable()){
            _thread.join();
        }
    }
};
​
void printHello(){
    std::cout << "Hello";
}
​
​
int main()
{
    MyThread m(printHello);
}

这就允许我们可以执行默认的行为,当然这不过是一个小demo,还有很多方法并没有实现,读者可以自行扩展之!

传递参数

我们注意到std::thread的参数无非就两处!第一个参数:可以被invoke(调用的),第二组是一个参数包,它表明了被调用的对象所需要的参数。

void task(int param, double t);
int d = 20;
double f = 30;
std::thread t(task, d, t);

如你所见,如果你查看std::thread的参数包中的声明类型是:Args...,这证明了我们传递的参数都是以拷贝的方式进行传递,这正是为了防止潜在的引用失效。

如果我们确实在移动一个巨大的对象,则可以手动触发std::move的方式提醒使用重载的参数移动构造的构造函数!

属性API

  • get_id():获取线程的ID,它将返回一个类型为std::thread::id的对象。

  • joinable():检查线程是否可被join。(我们没有办法对一个detach的线程做join!所以一个泛化的Join方法是)

    if(t.joinable()) // 是不是已经detach了?
        t.join()    // 不是detach的,选择join汇入主线程
  • std::thread::hardware_concurrency:我们知道并发度过高不会增加系统的效率(好奇为什么看我操作系统的关于进程调度的博客)所以我们需要确定当前系统的一个合适线程数目上限

Reference

std::thread - cppreference.com

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据集笔记:处理北大POI 数据:保留北京POI

数据来源&#xff1a;Map POI (Point of Interest) data - Official data of the contest (pku.edu.cn) windows 下载方法&#xff1a;数据集笔记&#xff1a;windows系统下载北大开放数据研究平台的POI数据-CSDN博客 1 读取数据 1.1 列出所有的文件 dir1D:/data/PKU POI/2…

如何管理约束

本文主要介绍如何管理约束&#xff0c;包括决定何时发生约束检查&#xff0c;如何删除约束&#xff0c;删除和更新父行&#xff0c;插入和更新子行。 1. 约束事务模式 约束事务模式决定何时发生引用违例检查。 对于具有日志记录的数据库 — 即时约束&#xff08;Immediate con…

【笔试强训】Day4 --- Fibonacci数列 + 单词搜索 + 杨辉三角

文章目录 1. Fibonacci数列2. 单词搜索3. 杨辉三角 1. Fibonacci数列 【链接】&#xff1a;Fibonacci数列 解题思路&#xff1a;简单模拟题&#xff0c;要最少的步数就是找离N最近的Fibonacci数&#xff0c;即可能情况只有比他小的最大的那个Fibonacci数以及比他大的最小的那…

【VUE】Vue中实现树状表格结构编辑与版本对比的详细技术实现

Vue中实现树状表格结构编辑与版本对比的详细技术实现 在Vue中&#xff0c;创建一个可编辑的树状表格并实施版本对比功能是一种需求较为常见的场景。在本教程中&#xff0c;我们将使用Vue结合Element UI的el-table组件&#xff0c;来构建一个树状表格&#xff0c;其中包含添加、…

ICCV 2021 | FcaNet: Frequency Channel Attention Networks 中的频率分析

ICCV 2021 | FcaNet: Frequency Channel Attention Networks 中的频率分析 论文&#xff1a;https://arxiv.org/abs/2012.11879代码&#xff1a;https://github.com/cfzd/FcaNet 文章是围绕 2D 的 DCT 进行展开的&#xff0c;本文针对具体的计算逻辑进行梳理和解析。 f ( u ,…

【MySQL精炼宝库】数据库的约束 | 表的设计 | 聚合查询 | 联合查询

目录 一、数据库约束 1.1 约束类型&#xff1a; 1.2 案例演示&#xff1a; 二、表的设计 2.1 一对一: 2.2 一对多: 2.3 多对多: 2.4 内容小结&#xff1a; 三、新增 四、查询 4.1 聚合查询&#xff1a; 4.1.1 聚合函数&#xff1a; 4.1.2 GROUP BY子句&#xff1a…

linux使用docker 安装mysql redis

linux安装docker https://hub-stage.docker.com/ 前往这里搜索容器来部署。每个容器都有独立的运行环境。 具体安装教程 https://docs.docker.com/engine/install/centos/#install-using-the-repository 检查是否安装成功&#xff1a; sudo docker --version 配置国内镜像加速…

人脸识别概念解析

目录 1. 概述 2. 人脸检测 3. 人脸跟踪 4. 质量评价 5. 活体检测 6. 特征提取 7. 人脸验证 8. 人脸辨识 1. 概述 人脸识别在我们的生活中随处可见&#xff0c;例如在大楼门禁系统中&#xff0c;它取代了传统的门禁卡或密码&#xff0c;提高了进出的便捷性和安全性。在商…

Adfind的使用

Adfind是一个使用C语言写的活动目录查询工具&#xff0c;它允许用户轻松地搜索各种活动目录信息。它不需要安装&#xff0c;因为它是基于命令行的。它提供了许多选项&#xff0c;可以细化搜索并返回相关细节。下面讲解Adfind的参数以及其使用。 参数 执行如下命令即可查看Adf…

ruoyi-nbcio-plus基于vue3的flowable为了适配文件上传改造VForm3的代码记录

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a; h…

Flutter笔记:DefaultTextStyle和DefaultTextHeightBehavior解读

Flutter笔记 DefaultTextStyle和DefaultTextHeightBehavior解读 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:htt…

PriorityQueue—优先级队列FollowUp

FollowUp大纲&#xff1a; 思维导图&#xff1a; FollowUp PriorityQueue: Q1&#xff1a;但不知道是大根堆化石小根堆 A&#xff1a;Q1 只需要放进去几个元素peek&#xff08;&#xff09;出元素是大的还是小的 下面如果是5就是小根堆10就是大根堆 A&#xff1a;默认是小根…

Github创建远程仓库(项目)

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

OPPO Reno10Pro/Reno11/K10手机强解BL刷root权限KSU内核抓包刷机救砖

OPPO Reno10Pro/Reno11/K10手机虽然发布时间并不久&#xff0c;但由于天玑处理器的体质&#xff0c;已经支持强制解锁BL了&#xff0c;该漏洞来自第三方工具适配&#xff0c;支持OPPO天机8100/8200刷机救砖解锁BL不需要等待官方深度测试直接实现。解锁BL后的OPPO Reno10Pro/Ren…

华为ensp中BGP(边界网关协议)基础原理及配置命令

作者主页&#xff1a;点击&#xff01; ENSP专栏&#xff1a;点击&#xff01; 创作时间&#xff1a;2024年4月27日10点04分 BGP&#xff08;边界网关协议&#xff09;是一种路由协议&#xff0c;用于在互联网中的不同自治系统&#xff08;AS&#xff09;之间交换路由信息。它…

Edge浏览器新特性深度解析,写作ai免费软件

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…

运算符重载(2)

1.赋值运算符重载 #include<iostream> using namespace std;class Person { friend void test01(); public:Person(int age){m_Age new int(age);}/*堆区的数据由程序员手动开辟并手动释放*/~Person(){if (m_Age ! NULL){delete m_Age;}}Person& operator(Person &a…

如此建立网络根文件系统 Mount NFS RootFS

安静NFS系统服务 sudo apt-get install nfs-kernel-server 创建目录 sudo mkdir /rootfsLee 将buildroot编译的根文件系统解压缩到 sudo tar xvf rootfs.tar -C /rootfsLee/ 添加文件NFS访问路径 sudo vi /etc/exports sudo /etc/exports文件&#xff0c;添加如下一行 …

比 PSD.js 更强的下一代 PSD 解析器,支持 WebAssembly

比 PSD.js 更强的下一代 PSD 解析器&#xff0c;支持 WebAssembly 1.什么是 webtoon/ps webtoon/ps 是 Typescript 中轻量级 Adobe Photoshop .psd/.psb 文件解析器&#xff0c;对 Web 浏览器和 NodeJS 环境提供支持&#xff0c;且做到零依赖。 Fast zero-dependency PSD par…

创建SpringBoot和RabbitMQ的整合项目

文章目录 创建SpringBoot和RabbitMQ的整合项目首先快速创建一个maven项目引入SpringBoot整合rabbitMQ的依赖在src/main目录下创建resources目录并引入配置文件写消息发送者MessageSender写消息接收者MessageReceiver写RabbitMQConfig配置类写SpringBoot启动主类CommandLineRunn…