C++:线程(thread)的创建、调用及销毁
在 C++ 中,线程的管理主要依赖于标准库 std::thread
,自 C++11 起,这一功能被标准化,使得我们能够更加方便地创建、管理和销毁线程。这里我们详细讲解线程的创建、调用和销毁流程。
1. 线程的创建
创建线程通常是为了在单独的线程中执行某个任务。我们可以通过 std::thread
对象来创建一个新的线程。一个线程可以从以下几种类型的可调用对象启动:
- 普通函数
- Lambda 表达式
- 函数对象
- 类的成员函数
1.1 使用普通函数
#include <iostream>
#include <thread>void printMessage() {std::cout << "Hello from thread!" << std::endl;
}int main() {std::thread myThread(printMessage); // 创建一个线程并启动 printMessagemyThread.join(); // 等待线程完成return 0;
}
std::thread myThread(printMessage)
创建一个线程对象myThread
,并启动执行printMessage
函数。myThread.join()
等待线程完成。如果没有调用join()
或detach()
,程序在结束时会崩溃。
1.2 使用 Lambda 表达式
#include <iostream>
#include <thread>int main() {std::thread myThread([]() {std::cout << "Hello from lambda!" << std::endl;});myThread.join();return 0;
}
- 这里我们创建了一个线程并使用 lambda 表达式作为线程函数。Lambda 允许我们在局部作用域中定义线程任务。
1.3 使用函数对象
#include <iostream>
#include <thread>class PrintTask {
public:void operator()() const {std::cout << "Hello from function object!" << std::endl;}
};int main() {std::thread myThread(PrintTask()); // 创建线程并启动myThread.join();return 0;
}
- 这是通过重载
operator()
来定义一个可调用的对象,该对象可以直接用来创建线程。
1.4 使用类的成员函数
#include <iostream>
#include <thread>class MyClass {
public:void memberFunction() {std::cout << "Hello from member function!" << std::endl;}
};int main() {MyClass obj;std::thread myThread(&MyClass::memberFunction, &obj); // 需要传递对象指针myThread.join();return 0;
}
- 如果是成员函数,则需要传递对象指针。
&MyClass::memberFunction
表示成员函数地址,&obj
是指向MyClass
实例的指针。
2. 线程的调用
-
线程的参数传递:你可以向线程函数传递参数,它们会按照值传递的方式进行复制。为了传递引用,可以使用
std::ref
或std::cref
。
#include <iostream>
#include <thread>void printNumber(int n) {std::cout << "Number: " << n << std::endl;
}int main() {int value = 42;std::thread myThread(printNumber, value);myThread.join(); // 等待线程完成return 0;
}
- 捕获引用:
void increment(int& n) {++n;
}int main() {int value = 0;std::thread myThread(increment, std::ref(value));myThread.join();std::cout << "Value after increment: " << value << std::endl;return 0;
}
这里 std::ref
确保 value
以引用的形式传递。
3. 线程的同步
join()
:主线程会等待myThread
结束。join
是同步机制,用于确保线程完成后主线程才会继续。
std::thread myThread(task);
myThread.join();
detach()
:将线程从主线程分离,让它独立运行。独立运行的线程在后台执行,主线程不再等待它完成。需谨慎使用,可能引发访问冲突。
std::thread myThread(task);
myThread.detach();
4. 线程的销毁
- 当
std::thread
对象离开作用域时,如果没有调用join()
或detach()
,程序会触发异常终止。 - 使用
join()
可以让主线程等待子线程完成,从而安全地销毁线程。 - 使用
detach()
可以将线程从std::thread
对象中分离,使其成为独立线程。调用detach()
后,std::thread
对象不再管理该线程。
5. 线程的生命周期管理
- RAII:考虑使用 RAII 类管理线程生命周期,确保在对象析构时
join()
或detach()
线程,从而避免泄漏和不正确的管理。
class ThreadGuard {
public:explicit ThreadGuard(std::thread& t) : thread(t) {}~ThreadGuard() {if (thread.joinable()) {thread.join();}}private:std::thread& thread;
};
6. 线程的注意事项
- 避免数据竞争和同步问题:线程共享数据时要小心。可以使用
std::mutex
进行保护,或者使用其他同步机制如std::lock_guard
。 - 避免内存泄漏:如果使用
new thread()
,确保delete
以释放分配的内存。 - 检查
joinable()
状态:调用join()
或detach()
前,可以用joinable()
检查线程状态。
7. 示例总结
#include <iostream>
#include <thread>void task(int id) {std::cout << "Thread " << id << " is running." << std::endl;
}int main() {std::thread t1(task, 1); // 创建线程并传递参数std::thread t2(task, 2);t1.join(); // 等待 t1 完成t2.join(); // 等待 t2 完成return 0;
}
8. 线程管理总结
- 使用
std::thread
创建和管理线程。 join()
和detach()
用于控制线程的生命周期。- 避免重复
join()
或detach()
,确保资源管理得当。 - 使用同步机制保护共享数据的访问。
通过这种方式,你可以更灵活地创建、管理和销毁 C++ 线程,确保程序的并发性和资源管理的安全性。
相关文章:
C++:线程(thread)的创建、调用及销毁
在 C 中,线程的管理主要依赖于标准库 std::thread,自 C11 起,这一功能被标准化,使得我们能够更加方便地创建、管理和销毁线程。这里我们详细讲解线程的创建、调用和销毁流程。 1. 线程的创建 创建线程通常是为了在单独的线程中执…...

关于随身wifi,看了再决定要不要买!2024年最受欢迎的随身wifi品牌推荐!
话费、流量费缴纳起来肉疼,毕竟不是每个月都有很大需求,主打一个该省省该花花。特别是短租人群、在校学生、出差或旅游的人群、追求高性价比的人群,随身Wifi特别实用,出门当WiFi,在家当宽带,两不耽误&#…...

SpringMVC总结 我的学习笔记
SpringMVC总结 我的学习笔记 一、SpringMVC简介1.MVC2.SpringMVC概述3. SpringMVC中的核心组件4.SpringMVC核心架构流程 二、SpringMVC框架实例具体实现使用注解实现 四、数据处理及跳转1.结果跳转方式2.处理器方法的参数与返回值处理提交数据数据显示到前端 五、RestFul风格1.…...

DevCheck Pro手机硬件检测工具v5.33
前言 DevCheck Pro是一款手机硬件和操作系统信息检测查看工具,该软件的功能非常强大,为用户提供了系统、硬件、应用程序、相机、网络、电池等一系列信息查看功能 安装环境 [名称]:DevCheckPro [版本]:5.33 [大小]&a…...
数据分析ReAct工作流
让我用一个数据分析项目的例子来展示plan-and-execute框架的应用。这个例子会涉及数据处理、分析和可视化等任务。 from typing import List, Dict, Any from dataclasses import dataclass import json from enum import Enum import logging from datetime import datetime#…...

Rust-AOP编程实战
文章本天成,妙手偶得之。粹然无疵瑕,岂复须人为?君看古彝器,巧拙两无施。汉最近先秦,固已殊淳漓。胡部何为者,豪竹杂哀丝。后夔不复作,千载谁与期? ——《文章》宋陆游 【哲理】文章…...
Flutter鸿蒙next 中的 Expanded 和 Flexible 使用技巧详解
在 Flutter 开发中,Expanded 和 Flexible 是两个非常常用的布局控件,它们可以帮助开发者更加灵活地管理 UI 布局的空间分配。虽然它们看起来非常相似,但它们的功能和使用场景有所不同。理解这两者的区别,能帮助你在构建复杂 UI 布…...

【微信小游戏学习心得】
这里是引用 微信小游戏学习心得 简介了解微信小游戏理解2d游戏原理数据驱动视图总结 简介 本人通过学习了解微信小游戏,学习微信小游戏,加深了对前端框架,vue和react基于数据驱动视图的理解,及浏览器文档模型和javaScript之间的关…...

Python | Leetcode Python题解之第539题最小时间差
题目: 题解: def getMinutes(t: str) -> int:return ((ord(t[0]) - ord(0)) * 10 ord(t[1]) - ord(0)) * 60 (ord(t[3]) - ord(0)) * 10 ord(t[4]) - ord(0)class Solution:def findMinDifference(self, timePoints: List[str]) -> int:n len…...

Zookeeper运维秘籍:四字命令基础、详解及业务应用全解析
文章目录 一、四字命令基础二、四字命令详解三、四字命令的开启与配置四、结合业务解读四字命令confconsenvi命令Stat命令MNTR命令ruok命令dump命令wchswchp ZooKeeper,作为一款分布式协调服务,提供了丰富的四字命令(也称为四字短语ÿ…...
Error: `slot-scope` are deprecated报错解决
本人新手菜鸡,文章为自己遇到问题的记录,如有错误或不足还请大佬批评指正 问题描述 在Vue3环境下使用slot插槽,出现‘slot-scope’ are deprecated报错问题,经过查找发现,是因为在slot插槽使用中,vue2和vu…...
Excel(图例)中使用上标下标
单元格中 1、在Excel单元格中刷黑要设置成上标的字符,如m2中的2; 2、单击右键,在弹出的对话框中选择“设置单元格格式”; 3、在弹出的“设置单元格格式”对话框中选择上标(或下标); 4、最后…...

熔断和降级
目录 隔离和降级 FeignClient整合Sentinel 通过Feign设置服务降级 1.创建类实现FallbackFactory接口,并让这个类和使用FeignClient的接口类绑定 2.让order-service服务的feign开启sentinel 3.测试,只开启order-service服务,而不开启user-…...

【学习笔记】Linux系统基础知识 6 —— su命令详解
提示:学习Linux系统基础命令 su 命令详解,包含通过 su 命令切换用户实例 一、前期准备 1.已经正确安装并成功进入Linux系统 说明:本实验采用的 Redhat 系统(因系统不一致,可能部分显示存在差异) 二、学…...
docker-compose命令介绍
docker-compose命令介绍 docker-compose1. docker-compose是什么2. Compose file format3. 命令3.1 服务相关命令upruncreatestartrestartdownstopkillrmpauseunpause 3.2 镜像相关命令3.3 查看相关命令 docker-compose 学了docker,然后就直接去学k8s了。恍恍惚惚几…...
Spring学习笔记_29——@Transactional
Transactional 1. 介绍 Transactional 是 Spring 框架提供的一个注解,用于声明方法或类级别的事务属性。 Spring事务:Spring学习笔记_28——事务-CSDN博客 当你在一个方法或类上使用 Transactional 注解时,Spring 会为该方法或类创建一个…...

github使用基础
要通过终端绑定GitHub账号并进行文件传输,你需要使用Git和SSH密钥来实现安全连接和操作。以下是一个基本流程: 设置GitHub和SSH 检查Git安装 通过终端输入以下命令查看是否安装Git: bash 复制代码 git --version配置Git用户名和邮箱 bash …...
Flink-Kafka-Connector
Apache Flink 是一个用于处理无界和有界数据的开源流处理框架。它支持高吞吐量、低延迟以及精确一次的状态一致性等特性。Flink 社区提供了丰富的连接器(Connectors)以方便与不同的数据源进行交互,其中就包括了 Apache Kafka 连接器。 Apach…...
远程终端vim里使用系统剪切板
1、本地通过终端远程linux server,由于不是桌面环境/GUI,终端vim里似乎没办法直接使用系统剪切板,即便已经是clipboard。 $ vim --version | grep clipboard clipboard keymap printer vertsplit eval …...

底层视角看C语言
文章目录 main函数很普通main函数之前调用了什么main函数和自定义函数的对比 变量名只为人而存在goto是循环的本质指针变量指针是一个特殊的数字汇编层面看指针 数组和指针数组越界问题低端地址越界高端地址越界 引用就是指针 main函数很普通 main函数是第一个被调用的函数吗&…...
Cesium1.95中高性能加载1500个点
一、基本方式: 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

python/java环境配置
环境变量放一起 python: 1.首先下载Python Python下载地址:Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个,然后自定义,全选 可以把前4个选上 3.环境配置 1)搜高级系统设置 2…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...

IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...
Webpack性能优化:构建速度与体积优化策略
一、构建速度优化 1、升级Webpack和Node.js 优化效果:Webpack 4比Webpack 3构建时间降低60%-98%。原因: V8引擎优化(for of替代forEach、Map/Set替代Object)。默认使用更快的md4哈希算法。AST直接从Loa…...

rknn toolkit2搭建和推理
安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 ,不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源(最常用) conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...