【C++并发编程】(二)线程的创建、分离和连接
文章目录
- (二)线程的创建、分离和链接
- 创建线程:示例
- 线程的分离(detach)和连接(join)
(二)线程的创建、分离和链接
创建线程:示例
线程(Thread)是并发执行的基本单位。在C++中,std::thread用于创建和管理线程。当你想在线程中执行某个有参数或无参数的函数时,你可以将该函数传递给std::thread创建的线程对象,以下是一些示例。
示例1:传递无参数函数
#include <iostream>
#include <thread>void print_hello() {std::cout << "Hello from thread!\n";
}int main() {// 创建一个 std::thread 类型的对象 t,并传递 print_hello作为t构造函数的参数。std::thread t(print_hello);t.join(); // 等待线程结束,下一节介绍其作用return 0;
}
示例2:传递带参数函数(拷贝)
#include <iostream>
#include <thread>void print_number(int num) {std::cout << "Number: " << num << '\n';
}int main() {int value = 42;std::thread t(print_number, value); // 创建线程,并传入参数(value 被拷贝给线程 )t.join(); // 等待线程结束return 0;
}
示例3:传递带参数函数(使用引用或指针)
如果你希望在线程中修改传入的参数值,可以用std::ref来包装参数,以便在创建线程时传递其引用。
#include <iostream>
#include <thread>void modify_number(int& num) {num *= 2;std::cout << "Modified number: " << num << '\n';
}int main() {int value = 42;std::thread t(modify_number, std::ref(value)); // 创建线程,并传入参数的引用t.join(); // 等待线程结束std::cout << "Value in main: " << value << '\n'; // 验证值已被修改return 0;
}
Modified number: 84
Value in main: 84
示例4:传递多个参数
你可以传递多个参数给线程函数。
#include <iostream>
#include <thread>void print_info(std::string name, int age) {std::cout << "Name: " << name << ", Age: " << age << '\n';
}int main() {std::string name = "Alice";int age = 30;std::thread t(print_info, name, age); // 创建线程,并传入多个参数t.join(); // 等待线程结束return 0;
}
示例5:传递类的成员函数和实例
你还可以传递类的成员函数和类的实例给线程。
#include <iostream>
#include <thread>class Person {
public:void say_hello(const std::string& greeting) {std::cout << greeting << " from " << name << '\n';}std::string name = "Bob";
};int main() {Person person;// 当线程 t 开始执行时,它会调用 person 对象的 say_hello 函数,并以 "Hello" 作为参数。std::thread t(&Person::say_hello, &person, "Hello"); // 创建线程,并传入成员函数和对象指针t.join(); // 等待线程结束return 0;
}
线程的分离(detach)和连接(join)
在C++中,线程的分离(detach)和连接(join)是用于管理线程生命周期的两种主要方式。当创建一个线程时,你可以选择让它独立运行(即分离),或者等待它完成执行(即连接)。
分离(detach)
当你调用std::thread::detach()方法时,你告诉线程库你不再关心这个线程的结束时间,并且你不需要获取它的返回值。线程将在后台独立运行,直到其函数返回,结束。
示例:
#include <iostream>
#include <thread>
#include <chrono>
#include <ctime>
#pragma warning(disable: 4996)
void thread_task() { // 阻塞当前线程的执行,直到指定的时间间隔(2s)过去 std::this_thread::sleep_for(std::chrono::seconds(2)); auto now = std::chrono::system_clock::now(); std::time_t now_c = std::chrono::system_clock::to_time_t(now); std::cout << "Hello from detached thread at " << std::ctime(&now_c) << std::endl;
} int main() { auto start_time = std::chrono::system_clock::now(); std::time_t start_time_c = std::chrono::system_clock::to_time_t(start_time); std::cout << "Main thread starts at " << std::ctime(&start_time_c) << std::endl; std::thread t(thread_task); // 创建线程 t.detach(); // 分离线程 // 主线程将不会等待t的结束,而是继续执行 std::cout << "Main thread continues execution without waiting for the detached thread.\n"; // 让主线程休眠3s,以便观察分离线程的输出 std::this_thread::sleep_for(std::chrono::seconds(3)); auto end_time = std::chrono::system_clock::now(); std::time_t end_time_c = std::chrono::system_clock::to_time_t(end_time); std::cout << "Main thread ends at " << std::ctime(&end_time_c) << std::endl; return 0;
}
在这个例子中,t线程将开始执行thread_task函数,并在调用t.detach()后立即返回主线程。主线程将继续执行,而不需要等待t线程的完成。
Main thread starts at Fri May 3 23:02:06 2024Main thread continues execution without waiting for the detached thread.
Hello from detached thread at Fri May 3 23:02:08 2024Main thread ends at Fri May 3 23:02:09 2024
开始和结束相差3秒。
连接(join)
当你调用std::thread::join()方法时,你告诉线程库你想要等待这个线程完成执行后再继续下去。调用join()的线程将被阻塞,直到被连接的线程执行完毕。
示例:
#include <iostream>
#include <thread>
#include <chrono>
#include <ctime>
#pragma warning(disable: 4996)
void thread_task() { // // 休眠2sstd::this_thread::sleep_for(std::chrono::seconds(2)); auto now = std::chrono::system_clock::now(); std::time_t now_c = std::chrono::system_clock::to_time_t(now); std::cout << "Hello from joined thread at " << std::ctime(&now_c) << std::endl;
} int main() { auto start_time = std::chrono::system_clock::now(); std::time_t start_time_c = std::chrono::system_clock::to_time_t(start_time); std::cout << "Main thread starts at " << std::ctime(&start_time_c) << std::endl; std::thread t(thread_task); // 创建线程 // 主线程将在这里阻塞,等待t的完成 t.join(); std::cout << "Main thread continues execution after the thread is joined.\n"; std::this_thread::sleep_for(std::chrono::seconds(3)); auto end_time = std::chrono::system_clock::now(); std::time_t end_time_c = std::chrono::system_clock::to_time_t(end_time); std::cout << "Main thread ends at " << std::ctime(&end_time_c) << std::endl; return 0;
}
在这个例子中,t线程将开始执行thread_task函数,而主线程在调用t.join()时将阻塞,等待t线程完成。当t线程完成后,主线程将继续执行。
Main thread starts at Fri May 3 23:11:45 2024Hello from joined thread at Fri May 3 23:11:47 2024Main thread continues execution after the thread is joined.
Main thread ends at Fri May 3 23:11:50 2024
开始和结束相差5秒。
相关文章:
【C++并发编程】(二)线程的创建、分离和连接
文章目录 (二)线程的创建、分离和链接创建线程:示例线程的分离(detach)和连接(join) (二)线程的创建、分离和链接 创建线程:示例 线程(Thread&a…...
利用生成式AI重新构想ITSM的未来
对注入 AI 的生成式 ITSM 的需求,在 2023 年 Gartner AI 炒作周期中,生成式 AI 达到预期值达到顶峰后,三分之二的企业已经将生成式 AI 集成到其流程中。 你问为什么这种追求?在预定义算法的驱动下,IT 服务交付和管理中…...
完美解决AttributeError: module ‘backend_interagg‘ has no attribute ‘FigureCanvas‘
遇到这种错误通常是因为matplotlib的后端配置问题。在某些环境中,尤其是在某些特定的IDE或Jupyter Notebook环境中,可能会因为后端配置不正确而导致错误。错误信息提示 module backend_interagg has no attribute FigureCanvas 意味着当前matplotlib的后…...
CMakeLists.txt语法规则:条件判断中表达式说明一
一. 简介 前面学习了 CMakeLists.txt语法中的 部分常用命令,常量变量,双引号的使用。 前面一篇文章也简单了解了 CMakeLists.txt语法中的条件判断,文章如下: CMakeLists.txt语法规则:条件判断说明一-CSDN博客 本文…...
《QT实用小工具·五十三》会跑走的按钮
1、概述 源码放在文章末尾 该项目实现了会逃跑的按钮: 两个按钮,一个为普通按钮,另一个为会跑走的按钮 鼠标移到上面时,立刻跑掉 针对鼠标、键盘、触屏进行优化 随机交换两个按钮的文字、偶尔钻到另一个按钮下面、鼠标移开自…...
Servlet的几种用法?
serlet 1.定义:Serlet是使用Java编写的运行在服务器端的程序 2.Servlet主要是用于处理浏览器端发送的Http请求,并返回一个响应 3.Servlet开发需要使用到的包: java.servlet java.servlet.http 一.Servlet注册 1.xml方式 <servlet>…...
Golang | Leetcode Golang题解之第69题x的平方根
题目: 题解: func mySqrt(x int) int {if x 0 {return 0}C, x0 : float64(x), float64(x)for {xi : 0.5 * (x0 C/x0)if math.Abs(x0 - xi) < 1e-7 {break}x0 xi}return int(x0) }...
AR人脸美妆SDK解决方案,让妆容更加贴合个人风格
美妆行业正迎来前所未有的变革,为满足企业对高效、精准、创新的美妆技术需求,美摄科技倾力打造了一款企业级AR人脸美妆SDK解决方案,为企业打开美妆领域的新世界大门。 革命性的人脸美妆技术 美摄科技的AR人脸美妆SDK解决方案,不…...
Python-100-Days: Day09 Object-oriented programming(OOP) Upgrade
1.property装饰器 之前有讨论过, Python中属性和方法访问权限的问题,不建议将属性设置为私有的,倘若直接将属性暴露给外界也是存在问题的。例如,我们没有办法检查赋给属性的值是否有效。之前的建议是将属性命名以单下划线开头&am…...
虹科Pico汽车示波器 | 免拆诊断案例 | 2010款凯迪拉克SRX车发动机无法起动
故障现象 一辆2010款凯迪拉克SRX车,搭载LF1发动机,累计行驶里程约为14.3万km。该车因正时链条断裂导致气门顶弯,大修发动机后试车,起动机运转有力,但发动机没有着机迹象;多起动几次,火花塞会变…...
ECC 号码总结
1、问题背景 在手机开发过程中,经常遇见各种紧急号码问题,在此特意总结下紧急号码相关知识。 2、紧急号码来源 在MTK RILD EccNumberSource.h中,定义了如下几种紧急号码来源。 按优先级排序介绍如下 2.1、SOURCE_NETWORK 网络下发ÿ…...
《大疆二次开发》EMQX和MQTT部署
EMQX 服务器 基础知识 概念 EMQX (Erlang/Enterprise/Elastic MQTT Broker) ;EMQ/EMQX就是MQTT Broker的一种实现;一款开源的大规模分布式 MQTT 消息服务器,功能丰富,专为物联网和实时通信应用而设计;支持多种协议&…...
【网络】滑动窗口和拥塞窗口
滑动窗口和拥塞窗口是TCP协议中两个重要的窗口概念,它们分别用于流量控制和拥塞控制,在功能和作用上有所不同。 滑动窗口(Sliding Window) 滑动窗口是用于流量控制的机制,它定义了发送方和接收方之间的数据传输量。T…...
数据库知识初步汇总
创建标签表格: CREATE TABLE IF NOT EXISTS labels (标签ID INTEGER PRIMARY KEY,标签名称 TEXT );创建文本与标签的关联表格: CREATE TABLE IF NOT EXISTS 文本标签 (文本ID INTEGER,标签ID INTEGER,FOREIGN KEY (文本ID) REFERENCES texts(编号),FOR…...
Moby简介:openEuler 中的开源docker引擎
Moby 是一个开源的容器化引擎,它提供了创建和管理容器所需的核心功能。在 openEuler 系统中,Moby 作为容器技术的实现之一,它允许用户利用容器化技术来部署、运行和移植应用程序。 Moby 的功能和作用: 1. **容器创建**ÿ…...
分布式光纤测温DTS的测温范围是多少?
分布式光纤测温DTS的测温范围不仅仅取决于光缆的感温能力,还受到多种复杂因素的影响。尽管高温光缆可以耐高温,低温光缆可以耐低温,甚至镀金光缆能够耐受高达700摄氏度的极高温度,然而,这些因素并不能完全解释测温范围…...
Java实现裁剪PDF
目录 安装Java PDF库 Java裁剪PDF页面 Java裁剪PDF页面并将结果保存为图片、HTML、Excel等格式 裁剪PDF页面是一项常见的任务,它可以用来调整文档的尺寸和去除不需要的边距或白边。通过裁剪页面,你可以优化文档的布局和展示效果,使其更符合…...
ZooKeeper以及DolphinScheduler的用法
目录 一、ZooKeeper的介绍 数据模型 编辑 操作使用 ①登录客户端 编辑 ②可以查看下面节点有哪些 ③创建新的节点,并指定数据 ④查看节点内的数据 ⑤、删除节点及数据 特殊点: 运行机制: 二、DolphinScheduler的介绍 架构&#…...
gitlab集群高可用架构拆分部署
目录 前言 负载均衡器准备 外部负载均衡器 内部负载均衡器 (可选)Consul服务 Postgresql拆分 1.准备postgresql集群 手动安装postgresql插件 2./etc/gitlab/gitlab.rb配置 3.生效配置文件 Redis拆分 1./etc/gitlab/gitlab.rb配置 2.生效配置文件 Gitaly拆分 1.…...
STC8增强型单片机开发day01
C51版本Keil环境搭建 搭建流程 环境搭建的基本流程: 从官方网站下载并安装Keil软件。选择安装的软件中的C51工具集并运行。通过从“文件”菜单中选择“项目”来创建新项目。输入项目名称并选择您正在使用的设备。通过从“项目”菜单中选择“添加文件到组”来添加…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
MySQL 部分重点知识篇
一、数据库对象 1. 主键 定义 :主键是用于唯一标识表中每一行记录的字段或字段组合。它具有唯一性和非空性特点。 作用 :确保数据的完整性,便于数据的查询和管理。 示例 :在学生信息表中,学号可以作为主键ÿ…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向
在人工智能技术呈指数级发展的当下,大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性,吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型,成为释放其巨大潜力的关键所在&…...
Axure零基础跟我学:展开与收回
亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...
OPENCV图形计算面积、弧长API讲解(1)
一.OPENCV图形面积、弧长计算的API介绍 之前我们已经把图形轮廓的检测、画框等功能讲解了一遍。那今天我们主要结合轮廓检测的API去计算图形的面积,这些面积可以是矩形、圆形等等。图形面积计算和弧长计算常用于车辆识别、桥梁识别等重要功能,常用的API…...
