C++:std::thread、条件变量与信号量
介绍
在多线程编程的世界里,协调不同线程之间的工作是一项极具挑战性的任务。线程可能需要等待特定条件的满足,或者对共享资源的访问进行限制。C++ 标准库为我们提供了强大的工具,如 std::thread 用于创建和管理线程,条件变量用于线程间的同步,信号量则用于控制对资源的访问。本文将通过具体的 C++ 代码示例,详细介绍如何使用这些工具。
std::thread 基础
std::thread 是 C++11 引入的用于创建和管理线程的类。它允许我们轻松地在程序中创建新的执行线程。下面是一个简单的 std::thread
#include <iostream>
#include <thread>void printMessage(const std::string& message) {std::cout << "Thread says: " << message << std::endl;
}int main() {std::thread t(printMessage, "Hello, World!");t.join();return 0;
}
定义了一个函数 printMessage,然后使用 std::thread 创建了一个新线程,并将 printMessage 函数作为线程的入口点,同时传递了一个字符串参数。join() 方法用于等待线程执行完毕。
条件变量
条件变量是一种同步原语,用于线程之间的通信和协调。它允许一个线程等待某个条件的满足,而另一个线程可以在条件满足时通知等待的线程。
生产者 - 消费者模型示例
生产者 - 消费者模型是多线程编程中常见的模式,生产者线程负责生产数据,消费者线程负责消费数据。我们可以使用条件变量来实现线程间的同步。
#include <iostream>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>std::queue<int> dataQueue;
std::mutex mtx;
std::condition_variable cv;
bool isProducing = true;// 生产者线程函数
void producer() {for (int i = 0; i < 5; ++i) {std::this_thread::sleep_for(std::chrono::seconds(1));{std::unique_lock<std::mutex> lock(mtx);dataQueue.push(i);std::cout << "Produced: " << i << std::endl;}cv.notify_one();}{std::unique_lock<std::mutex> lock(mtx);isProducing = false;}cv.notify_one();
}//消费者线程函数
void consumer() {while (true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, [] { return!dataQueue.empty() ||!isProducing; });if (!dataQueue.empty()) {int value = dataQueue.front();dataQueue.pop();std::cout << "Consumed: " << value << std::endl;} else if (!isProducing) {break;}}
}int main() {std::thread producerThread(producer);std::thread consumerThread(consumer);producerThread.join();consumerThread.join();return 0;
}
std::queue dataQueue:用于存储生产者生产的数据。
std::mutex mtx:用于保护对 dataQueue 的访问,确保线程安全。
std::condition_variable cv:用于线程间的同步。
producer() 函数:生产者线程每隔 1 秒生产一个数据,并将其加入队列。生产完成后,通知消费者线程。
consumer() 函数:消费者线程等待条件变量的通知,当队列中有数据时,从队列中取出数据进行消费。
cv.wait(lock, [] { return!dataQueue.empty() ||!isProducing; }):消费者线程等待,直到队列非空或者生产结束。
信号量
信号量是一种用于控制对资源访问的同步原语。在 C++ 标准库中,并没有直接提供信号量的实现,可以使用 std::mutex 和 std::condition_variable 来模拟信号量。
信号量的实现
#include <mutex>
#include <condition_variable>class Semaphore {
public:Semaphore(int count = 0) : count_(count) {}void notify() {std::unique_lock<std::mutex> lock(mtx_);++count_;cv_.notify_one();}void wait() {std::unique_lock<std::mutex> lock(mtx_);cv_.wait(lock, [this] { return count_ > 0; });--count_;}private:int count_;std::mutex mtx_;std::condition_variable cv_;
};
#include <iostream>
#include <thread>
#include <vector>Semaphore sem(2); // 允许最多 2 个线程同时访问资源void accessResource(int id) {sem.wait();std::cout << "Thread " << id << " is accessing the resource." << std::endl;std::this_thread::sleep_for(std::chrono::seconds(2));std::cout << "Thread " << id << " has finished accessing the resource." << std::endl;sem.notify();
}int main() {std::vector<std::thread> threads;for (int i = 0; i < 5; ++i) {threads.emplace_back(accessResource, i);}for (auto& t : threads) {t.join();}return 0;
}
Semaphore 类:实现了一个简单的信号量。notify() 方法用于增加信号量的值并通知等待的线程,wait() 方法用于等待信号量的值大于 0 并减少信号量的值。
accessResource() 函数:线程在访问资源前调用 sem.wait() 等待信号量,访问完成后调用 sem.notify() 释放信号量。
emplace_back 是 C++ 标准库容器(如 std::vector、std::deque 等)提供的一个成员函数,它主要用于在容器的尾部直接构造一个新元素。
结论
通过 std::thread、条件变量和信号量,可以在 C++ 中实现复杂的多线程程序。条件变量用于线程间的同步,确保线程在特定条件满足时才继续执行;信号量用于控制对资源的访问,避免资源竞争。合理使用这些工具可以提高程序的性能和稳定性。希望本文能帮助你更好地理解和应用这些多线程编程的重要概念。
相关文章:
C++:std::thread、条件变量与信号量
介绍 在多线程编程的世界里,协调不同线程之间的工作是一项极具挑战性的任务。线程可能需要等待特定条件的满足,或者对共享资源的访问进行限制。C 标准库为我们提供了强大的工具,如 std::thread 用于创建和管理线程,条件变量用于线…...
POI pptx转图片
前言 ppt页面预览一直是个问题,office本身虽然有预览功能但是收费,一些开源的项目的预览又不太好用,例如开源的:kkfileview pptx转图片 1. 引入pom依赖 我这个项目比较老,使用版本较旧 <dependency><gro…...
Java File 类
File 类是 Java 中用于处理文件和目录的基本类之一,位于 java.io 包中。它提供了多种方法来创建、删除、检查、修改文件或目录的属性,以及列出文件夹中的内容。虽然 File 类本身不提供直接的读取或写入文件内容的方法(这些操作通常由 FileInp…...
工业通信协议 EtherNet/IP 全面解析
工业通信协议 EtherNet/IP 全面解析 EtherNet/IP(以太网工业协议)是一种基于标准以太网的工业自动化通信协议,由 ODVA(开放设备网供应商协会) 管理。它融合了 CIP(通用工业协议) 和以太网技术&…...
使用docker配置PostgreSQL
配置docker阿里云镜像仓库 国内使用docker hub拉取镜像比较慢,所以首先配置个人的镜像仓库。 阿里云的个人镜像仓库是免费的,对个人来说足够用。 具体操作参考阿里云官方链接 。 关于个人镜像仓库的使用参考链接。 配置完个人镜像仓库后将公网配置到doc…...
UITextView删除原有字符串时,光标会上移并且光标会变高
代码运行效果如图: import Foundationclass TestVC: UIViewController {override func viewDidLoad() {super.viewDidLoad()let testV MyCustomTextView(frame: CGRect(x: 0, y: 130, width: SCREEN_WIDTH - 50, height: 170))self.view.addSubview(testV)testV.ba…...
python入门 介绍及变量的使用
1.python介绍 python 是一门计算机语言 常见的计算机语言:python、java、C语言。。。 什么是计算机语言:就是让计算机知道你想干什么,把你的需求使用它能听懂的语言说出来 中国也有一门计算机语言:易语言 能认为是语言的本质上…...
51单片机-按键
1、独立按键 1.1、按键介绍 轻触开关是一种电子开关,使用时,轻轻按开关按钮就可使开关接通,当松开手时,开关断开。 1.2、独立按键原理 按键在闭合和断开时,触点会存在抖动现象。P2\P3\P1都是准双向IO口,…...
Java 8 至 Java 23 版本特性对比表
Java现在发布的版本很快,每年两个,但是真正会被大规模使用的是三年一个的TLS版本。 版本年份LTS关键特性影响力等级Java 82014✅Lambda 表达式、Stream API、方法引用、接口默认方法、Optional 类⭐⭐⭐⭐⭐Java 92017❌模块化系统(JPMS&…...
在wsl环境中配置和开发verilog(一种比较新颖的verilog开发指南)
WSL是windows中自带的linux子系统,笔者在若干月前首次接触其便爱不释手,verilog作为一种硬件解释语言,可否像c语言那样被游刃有余的编译和运行呢,笔者这次大胆的尝试在WSL环境VSCODEIverilog开发verilog。 首先默认按照了WSL和VS…...
AI学习指南HuggingFace篇-Hugging Face 的核心工具
一、引言 Hugging Face作为AI领域的重要参与者,提供了许多强大的工具,极大地简化了自然语言处理(NLP)任务的开发流程。其中,Transformers、Datasets 和 Tokenizers 是Hugging Face的三大核心工具。本文将深入介绍这些工具的作用、功能以及它们如何相互配合,帮助读者更好…...
DeepSeek 助力 Vue 开发:打造丝滑的二维码生成(QR Code)
前言:哈喽,大家好,今天给大家分享一篇文章!并提供具体代码帮助大家深入理解,彻底掌握!创作不易,如果能帮助到大家或者给大家一些灵感和启发,欢迎收藏关注哦 💕 目录 Deep…...
QT 引入Quazip和Zlib源码工程到项目中,无需编译成库,跨平台,压缩进度
前言 最近在做项目时遇到一个需求,需要将升级的文件压缩成zip,再进行传输; 通过网络调研,有许多方式可以实现,例如QT私有模块的ZipReader、QZipWriter;或者第三方库zlib或者libzip或者quazip等࿱…...
深入解析桥接模式:软件设计中的解耦利器
桥接模式:软件设计中的解耦利器 在软件开发的复杂世界中,设计模式是开发者解决常见问题的有力工具。桥接模式作为一种重要的结构型设计模式,在处理抽象与实现的关系时展现出独特的优势,它能够巧妙地将抽象部分与实现部分分离&…...
MYSQL-数据库-DDL-DML-DQL-DCL-基础学习
MySql概念: 建立在关系模型基础上,有多张相互连接的二维表组成的数据库 SQL通用语法: 1.SQL语句可以单行或多行书写,以分号结尾 2.SQL语句可以使用空格/缩进来增强语句的可读性 3.MySQL数据库的SQL语句不区分大小写,关…...
rv1126解码的一些原理
rv1126解码篇中,出现最重要的两个api一个是,send_vdec_thread线程里面调用的RK_MPI_SYS_SendMediaBuffer,把数据发到解码器。另外一个是read_vdec_thread线程的RK_MPI_SYS_GetMediaBuffer获取解码器里面的数据。 今天想探讨一下他的底层原理。…...
二级公共基础之数据结构与算法篇(七)排序技术
目录 前言 一、交换类排序 1.冒泡排序法 1. 冒泡排序的思想 2. 冒泡排序的实现步骤 3. 示例 4. 冒泡排序的特点 2.快速排序 1. 快速排序的核心思想 2. 快速排序的实现步骤 3. 示例代码(C语言) 4. 快速排序的特点 二、插入类排序 1. 简单插入排序 1.简单插入排…...
深蕾科技智能多媒体SoC产品助力“DataEye剧查查之夜”微短剧盛会
深蕾科技助力微短剧盛会 深圳湾“DataEye剧查查之夜”微短剧盛会,于2025年2月20日18:00点,在深圳湾盛大开启。作为第十四届中国国际新媒体短片节的重要组成部分,“剧查查之夜”汇聚了微短剧行业的顶尖力量,吸引了众多大咖齐聚一堂…...
Apache Doris 实现毫秒级查询响应
1. 引言 1.1 数据分析的重要性 随着大数据时代的到来,企业对实时数据分析的需求日益增长。快速、准确地获取数据洞察成为企业在竞争中脱颖而出的关键。传统的数据库系统在处理大规模数据时往往面临性能瓶颈,难以满足实时分析的需求。例如,一个电商公司需要实时监控销售数据…...
计算机考研之数据结构:P 问题和 NP 问题
在算法的时间复杂度估算中,通常教材和题目中的估算结果包括: O ( 1 ) , O ( log n ) , O ( n ) , O ( n ) , O ( n log n ) , O ( n 2 ) , O ( n 3 ) , O ( log log n ) O(1),O(\log{n}),O(\sqrt{n}),O(n),O(n\log{n}),O(n^2),O(n^3),O(\log…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
LeetCode - 199. 二叉树的右视图
题目 199. 二叉树的右视图 - 力扣(LeetCode) 思路 右视图是指从树的右侧看,对于每一层,只能看到该层最右边的节点。实现思路是: 使用深度优先搜索(DFS)按照"根-右-左"的顺序遍历树记录每个节点的深度对于…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
SpringAI实战:ChatModel智能对话全解
一、引言:Spring AI 与 Chat Model 的核心价值 🚀 在 Java 生态中集成大模型能力,Spring AI 提供了高效的解决方案 🤖。其中 Chat Model 作为核心交互组件,通过标准化接口简化了与大语言模型(LLM࿰…...
