<C++学习>C++ std 多线程教程
C++ std
多线程教程
理解多线程的概念
多线程是一种并发编程技术,它允许程序同时运行多个任务。每个线程共享同一进程的资源(如内存),但拥有独立的执行路径。多线程编程在现代 C++ 中变得更加便捷和安全,标准库提供了强大的多线程支持,包括线程创建、同步和管理。
多线程的优点
- 提高性能:充分利用多核 CPU 的并行计算能力。
- 异步操作:后台任务(如文件处理、网络通信)可以在不阻塞主线程的情况下运行。
- 简化复杂任务:将复杂任务分解为多个线程独立处理。
C++ 提供的多线程支持
C++11 开始标准库新增了 <thread>
模块,用于线程管理,并提供同步机制(如互斥锁、条件变量)。
1. C++ 多线程基础
1.1 创建线程
通过 std::thread
创建线程。线程可以执行:
- 函数。
- Lambda 表达式。
- 成员函数。
示例
#include <iostream>
#include <thread>void printMessage() {std::cout << "Hello from thread!" << std::endl;
}int main() {std::thread t(printMessage); // 创建线程 tt.join(); // 等待线程 t 执行完毕return 0;
}
1.2 线程的生命周期
- 创建:通过
std::thread
创建新线程。 - 加入:
join()
:主线程等待子线程完成。detach()
:分离线程,子线程独立运行。
- 结束:线程完成任务或被终止。
示例:detach
和 join
#include <iostream>
#include <thread>void detachedThread() {std::cout << "Detached thread running..." << std::endl;
}void joinedThread() {std::cout << "Joined thread running..." << std::endl;
}int main() {std::thread t1(detachedThread);t1.detach(); // 分离线程,主线程不再管理它std::thread t2(joinedThread);t2.join(); // 主线程等待 t2 完成std::cout << "Main thread finished." << std::endl;return 0;
}
1.3 Lambda 表达式作为线程函数
示例
#include <iostream>
#include <thread>int main() {std::thread t([] {std::cout << "Hello from Lambda!" << std::endl;});t.join();return 0;
}
1.4 传递参数到线程
通过 std::thread
构造函数将参数传递给线程函数。
示例
#include <iostream>
#include <thread>void printNumbers(int n, const std::string& message) {for (int i = 0; i < n; i++) {std::cout << message << " " << i << std::endl;}
}int main() {std::thread t(printNumbers, 5, "Count"); // 传递参数 5 和 "Count"t.join();return 0;
}
2. 线程同步
多线程共享资源时,可能会导致数据竞争(race condition)。C++ 提供了多种同步机制来解决这些问题。
2.1 互斥锁(std::mutex
)
示例:保护共享资源
#include <iostream>
#include <thread>
#include <mutex>std::mutex mtx; // 定义一个互斥锁
int counter = 0;void increment() {for (int i = 0; i < 100; i++) {std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁counter++;}
}int main() {std::thread t1(increment);std::thread t2(increment);t1.join();t2.join();std::cout << "Final counter value: " << counter << std::endl;return 0;
}
2.2 条件变量(std::condition_variable
)
条件变量用于线程间通信和同步。
示例:生产者-消费者模型
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>std::queue<int> q;
std::mutex mtx;
std::condition_variable cv;void producer() {for (int i = 0; i < 10; i++) {std::unique_lock<std::mutex> lock(mtx);q.push(i);std::cout << "Produced: " << i << std::endl;cv.notify_one(); // 通知消费者}
}void consumer() {for (int i = 0; i < 10; i++) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return !q.empty(); }); // 等待队列非空int item = q.front();q.pop();std::cout << "Consumed: " << item << std::endl;}
}int main() {std::thread t1(producer);std::thread t2(consumer);t1.join();t2.join();return 0;
}
3. 多线程的Linux Demo
以下示例演示了如何在 Linux 环境下编写一个多线程程序,该程序计算数组的部分和,并最终输出总和。
完整代码
#include <iostream>
#include <thread>
#include <vector>
#include <numeric>
#include <functional>void partialSum(const std::vector<int>& data, int start, int end, int& result) {result = std::accumulate(data.begin() + start, data.begin() + end, 0);std::cout << "Partial sum [" << start << ", " << end << ") = " << result << std::endl;
}int main() {const int size = 100;std::vector<int> data(size);std::iota(data.begin(), data.end(), 1); // 初始化数组 [1, 2, ..., 100]int numThreads = 4;int blockSize = size / numThreads;std::vector<std::thread> threads;std::vector<int> results(numThreads);// 启动线程for (int i = 0; i < numThreads; i++) {int start = i * blockSize;int end = (i == numThreads - 1) ? size : start + blockSize;threads.emplace_back(partialSum, std::cref(data), start, end, std::ref(results[i]));}// 等待线程完成for (auto& t : threads) {t.join();}// 计算总和int totalSum = std::accumulate(results.begin(), results.end(), 0);std::cout << "Total sum: " << totalSum << std::endl;return 0;
}
运行示例
在 Linux 环境中编译和运行:
g++ -std=c++11 -pthread -o multithreading_demo multithreading_demo.cpp
./multithreading_demo
结果示例
Partial sum [0, 25) = 325
Partial sum [25, 50) = 950
Partial sum [50, 75) = 1575
Partial sum [75, 100) = 2200
Total sum: 5050
学习建议
- 理解线程的生命周期:掌握线程的创建、管理和结束。
- 同步机制:熟悉
std::mutex
和std::condition_variable
的使用。 - 多线程调试:在 Linux 中使用工具(如
gdb
)调试多线程程序。
通过这些内容,你可以编写高效的 C++ 多线程程序,并在实际项目中灵活运用!
相关文章:
<C++学习>C++ std 多线程教程
C std 多线程教程 理解多线程的概念 多线程是一种并发编程技术,它允许程序同时运行多个任务。每个线程共享同一进程的资源(如内存),但拥有独立的执行路径。多线程编程在现代 C 中变得更加便捷和安全,标准库提供了强大…...

用 Python 自动化处理日常任务
💖 欢迎来到我的博客! 非常高兴能在这里与您相遇。在这里,您不仅能获得有趣的技术分享,还能感受到轻松愉快的氛围。无论您是编程新手,还是资深开发者,都能在这里找到属于您的知识宝藏,学习和成长…...
《深入浅出HTTPS》读书笔记(28):DSA数字签名
《深入浅出HTTPS》读书笔记(28):DSA数字签名 对称加密算法有很多算法,标准算法是RSA机密算法,数字签名技术也有一个标准DSS(Digital Signature Standard),其标准…...
type 属性的用途和实现方式(图标,表单,数据可视化,自定义组件)
1.图标类型 <uni-icon>组件中,type可以用来指定图标的不同样式。 <uni-icons type"circle" size"30" color"#007aff"></uni-icons> //表示圆形 <uni-icons type"square" size"30" co…...

PSINS工具箱学习(四)捷联惯导更新算法
原始 Markdown文档、Visio流程图、XMind思维导图见:https://github.com/LiZhengXiao99/Navigation-Learning 文章目录 一、捷联惯导更新1、insinit():初始化 ins 结构体2、ethupdate():地球自转角速度和牵连角速度更新3、insupdate():捷联惯导更新1. 速度更新2. 位置更新3.…...

P1Linux和Docker常用终端命令:保姆级图文详解
文章目录 前言1、Docker 常用命令1.1、镜像管理1.2、容器管理1.3、网络管理1.4、数据卷管理1.5、监控和性能管理 2、Linux 常用命令分类2.1、文件和目录管理2.2、用户管理2.3、系统监控和性能2.4、软件包管理2.5、网络管理 前言 亲爱的家人们,创作很不容易…...

Windows重装后NI板卡LabVIEW恢复正常
在重新安装Windows系统后,NI(National Instruments)板卡能够恢复正常工作,通常是由于操作系统的重新配置解决了之前存在的硬件驱动、兼容性或配置问题。操作系统重装后,系统重新加载驱动程序、清理了潜在的冲突或损坏的…...
深度解析统计学四大分布:Z、卡方、t 与 F 的关联与应用
统计学关键分布:Z、卡方、t、F 的关系探秘与应用指南 A/B实验系列相关文章(置顶) 1. A/B实验之置信检验(一):如何避免误判和漏报 2. A/B实验之置信检验(二):置信检验精要…...
zkServer.sh脚本
Apache ZooKeeper 几种常见的方法: 一、使用 zkServer.sh 脚本: 最常见的启动 ZooKeeper 的方式是使用提供的 zkServer.sh 脚本。此脚本可用于管理 ZooKeeper 进程。以下是一些示例命令: 1. 在前台启动 ZooKeeper: ./zkServer.s…...

CV(10)--目标检测
前言 仅记录学习过程,有问题欢迎讨论 目标检测 object detection,就是在给定的图片中精确找到物体所在位置,并标注出物体的类别;输出的是分类类别label物体的外框(x, y, width, height)。 目标检测算法:…...

UML系列之Rational Rose笔记七:状态图
一、新建状态图 依旧是新建statechart diagram; 二、工作台介绍 接着就是一个状态的开始:开始黑点依旧可以从左边进行拖动放置: 这就是状态的开始,和活动图泳道图是一样的;只能有一个开始,但是可以有多个…...
C++单例模式的设计
单例模式(Singleton Pattern)是一种设计模式,用于确保一个类只有一个实例,并提供一个全局访问点来访问该实例。在C中,单例模式通常用于管理全局资源或共享状态。 以下是C中实现单例模式的几种常见方式: 懒…...

基于springboot的自习室预订系统
作者:学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等 文末获取“源码数据库万字文档PPT”,支持远程部署调试、运行安装。 项目包含: 完整源码数据库功能演示视频万字文档PPT 项目编码࿱…...

shell笔记
1.使用 ls -l 及 find 查找某个或者多个目录文件数量时 单个目录: find 目录 -type f|wc -l与 ls -l 目录|grep -v total|wc -l 一致 多个目录:如上结果不一致,因为 ls -l 在算多目录时,会将多目录及空格打出算作额外行 find 更精…...
《鸿蒙Next微内核:解锁人工智能决策树并行计算的加速密码》
在当今人工智能飞速发展的时代,提升运算速度是推动其进步的关键。鸿蒙Next以其独特的微内核特性,为设计决策树的并行计算框架提供了新的思路和契机。 鸿蒙Next微内核特性概述 鸿蒙Next的微内核架构将核心功能模块化,仅保留进程管理、内存管…...

AI刷题-最大矩形面积问题、小M的数组变换
目录 一、最大矩形面积问题 问题描述 输入格式 输出格式 输入样例 输出样例 数据范围 解题思路: 问题理解 数据结构选择 算法步骤 最终代码: 运行结果: 二、小M的数组变换 问题描述 测试样例 解题思路: 问题…...
Redis集群部署详解:主从复制、Sentinel哨兵模式与Cluster集群的工作原理与配置
集群部署形式 1、主从复制1.1 工作机制1.2 配置实现1.3 优缺点1.4 部署形式1.5 主从复制优化 2、Sentinel 哨兵模式2.1 工作机制2.2 配置实现2.3 优缺点2.4 哨兵机制选举流程2.5 脑裂问题解决方案 3、Redis Cluster3.1 工作机制3.2 配置实现3.3 优缺点3.4 故障转移3.5 哈希槽为…...

LeetCode热题100(三十四) —— 23.合并K个升序链表
LeetCode热题100(三十四) —— 23.合并K个升序链表 题目描述代码实现思路一:选择排序(199ms)思路二:归并排序(2ms) 思路解析 你好,我是杨十一,一名热爱健身的程序员在Coding的征程中,不断探索与…...

kalilinux - 目录扫描之dirsearch
情景导入 先简单介绍一下dirsearch有啥用。 假如你现在访问一个网站,例如https://www.example.com/ 它是一个电商平台或者其他功能性质的平台。 站在开发者的角度上思考,我们只指导https://www.example.com/ 但不知道它下面有什么文件,文…...

浅谈云计算04 | 云基础设施机制
探秘云基础设施机制:云计算的基石 一、云基础设施 —— 云计算的根基二、核心机制之网络:连接云的桥梁(一)虚拟网络边界ÿ…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
ES6从入门到精通:前言
ES6简介 ES6(ECMAScript 2015)是JavaScript语言的重大更新,引入了许多新特性,包括语法糖、新数据类型、模块化支持等,显著提升了开发效率和代码可维护性。 核心知识点概览 变量声明 let 和 const 取代 var…...

Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
CMake控制VS2022项目文件分组
我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...

淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...