C++|四种方法解决三线程按顺序轮流打印ABC的问题:互斥锁和条件变量、原子操作、信号量

基于Pthreads线程库的实现

g++ your_program.cpp -lpthread

编译时确保链接了Pthreads库.

#include <pthread.h>
#include <iostream>
#include <unistd.h>// 全局变量,用于控制打印顺序
int turn = 0;
// 定义互斥锁和条件变量
pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;void* printA(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&lock);while (turn != 0) {pthread_cond_wait(&cond, &lock);}std::cout << "A ";turn = 1;pthread_cond_broadcast(&cond);pthread_mutex_unlock(&lock);}return NULL;
}void* printB(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&lock);while (turn != 1) {pthread_cond_wait(&cond, &lock);}std::cout << "B ";turn = 2;pthread_cond_broadcast(&cond);pthread_mutex_unlock(&lock);}return NULL;
}void* printC(void* arg) {for (int i = 0; i < 10; i++) {pthread_mutex_lock(&lock);while (turn != 2) {pthread_cond_wait(&cond, &lock);}std::cout << "C ";turn = 0;pthread_cond_broadcast(&cond);pthread_mutex_unlock(&lock);}return NULL;
}int main() {pthread_t t1, t2, t3;pthread_create(&t1, NULL, printA, NULL);pthread_create(&t2, NULL, printB, NULL);pthread_create(&t3, NULL, printC, NULL);pthread_join(t1, NULL);pthread_join(t2, NULL);pthread_join(t3, NULL);pthread_mutex_destroy(&lock);pthread_cond_destroy(&cond);return 0;
}

互斥锁和条件变量

#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
using namespace std;class PrintABC {
public:PrintABC(int count) : count_(count) { }void printA () {for (int i = 0; i < count_; ++i) {std::unique_lock<std::mutex> lock(mtx_);//等待turn_变为0cv_.wait(lock, [this]() { return turn_ == 0; });std::cout << "a" << endl;//设置下一个轮次为1,并通知等待的线程turn_ = 1;cv_.notify_all();}}void printB () {for (int i = 0; i < count_; ++i) {std::unique_lock<std::mutex> lock(mtx_);//等待turn_变为0cv_.wait(lock, [this]() { return turn_ == 1; });std::cout << "b" << endl;//设置下一个轮次为1,并通知等待的线程turn_ = 2;cv_.notify_all();}}void printC () {for (int i = 0; i < count_; ++i) {std::unique_lock<std::mutex> lock(mtx_);//等待turn_变为0cv_.wait(lock, [this]() { return turn_ == 2; });std::cout << "c" << endl;//设置下一个轮次为1,并通知等待的线程turn_ = 0;cv_.notify_all();}}
private:std::mutex mtx_;std::condition_variable cv_;int turn_ = 0;  //控制打印顺序,0代表打印a,1代表打印b,2代表打印c,int count_; //打印次数
};int main () {int printCount = 10; //设定打印次数PrintABC printABC(printCount);std::thread t1(&PrintABC::printA, &printABC);std::thread t2(&PrintABC::printB, &printABC);std::thread t3(&PrintABC::printC, &printABC);t1.join();t2.join();t3.join();return 0;
}

原子变量

无锁实现控制打印顺序,但会占用更多的CPU资源,因为线程在等待时处于忙等(busy-waiting)状态。

#include <iostream>
#include <thread>
#include <atomic>volatile std::atomic<int> turn(0);void printA(int count) {for (int i = 0; i < count; ++i) {while(turn != 0); // 忙等std::cout << "a";turn = 1;}
}void printB(int count) {for (int i = 0; i < count; ++i) {while(turn != 1); // 忙等std::cout << "b";turn = 2;}
}void printC(int count) {for (int i = 0; i < count; ++i) {while(turn != 2); // 忙等std::cout << "c";turn = 0;}
}int main() {int count = 10;std::thread a(printA, count);std::thread b(printB, count);std::thread c(printC, count);a.join();b.join();c.join();std::cout << "\n";return 0;
}

信号量

C++20之后引入的库,才使得C++语言级别的信号量实现,
编译的时候记得加一个-std=c++20

#include <iostream>
#include <thread>
#include <semaphore>std::counting_semaphore semA(1); // 初始计数为1,A可以立即打印
std::counting_semaphore semB(0); // 初始计数为0,B需要等待A释放
std::counting_semaphore semC(0); // 初始计数为0,C需要等待B释放void printA(int count) {for (int i = 0; i < count; ++i) {semA.acquire();std::cout << "a" << std::endl;semB.release();}
}void printB(int count) {for (int i = 0; i < count; ++i) {semB.acquire();std::cout << "b" << std::endl;semC.release();}
}void printC(int count) {for (int i = 0; i < count; ++i) {semC.acquire();std::cout << "c" << std::endl;semA.release();}
}int main() {int count = 10; // 每个线程打印10次std::thread a(printA, count);std::thread b(printB, count);std::thread c(printC, count);a.join();b.join();c.join();std::cout << "\n";return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【#4 如何选择激活函数:深度学习中的关键决策】

文章目录 前言第一部分&#xff1a;激活函数的基础知识1.1 激活函数简介1.2 激活函数的作用 第二部分&#xff1a;选择激活函数的考虑因素2.1 网络层级2.2 任务类型2.3 训练稳定性2.4 计算效率2.5 网络深度 第三部分&#xff1a;流行激活函数的特点与应用场景3.1 Sigmoid3.2 Re…

技术面‍:前端代码是如何与服务器交互的

前言&#xff1a; 本篇文章主要是想讲解 .html 文件和 .CSS 文件在实际开发中和后端服务器交互最后上线的基础原理。 面向的人群&#x1f195;&#xff1a;是刚入行不久&#xff0c;且目前只会写前端业务代码而不清楚整个工作流的前端新人。我会从 0 开始一步一步带你理解整个…

QT打包命令的使用

QT打包命令的使用 windeployqt untitled1.exe windeployqt -qmldir C:\Users\unikinfo\Documents\UNIKINFO\untitled\YNMapDisplay YNMapDisplay.dll linuxdeployqt 程序文件 -qmldirqml源码路径 -appimage

大规模敏捷SA(Leading SAFe)证书是什么意思?如何报名,含金量高吗?

大规模敏捷SA(Leading SAFe)证书是什么意思&#xff1f; 常规的敏捷框架适用于中小型项目团队&#xff0c;而且不具有扩展性。基于常规的敏捷框架&#xff0c;SAFe定义了一个可扩展的敏捷框架模型&#xff0c;它适用于大型团队的合作开发&#xff0c;可以提高团队之间的协作性…

备份工具 - dd 命令

目录 一、命令格式 二、示例 1.备份文件 2.备份分区到文件 3.备份整个硬盘 4.备份分区到另一个分区 5.测试cpu、磁盘 一、命令格式 dd 复制文件 命令格式&#xff1a;dd if“输入文件” of“输出文件” bs“数据块” count“数量”参数&#xff1a;if&#xff1a; # 定…

【再探】设计模式—职责链模式、命令模式及迭代器模式

行为型设计模式研究系统在运行时对象之间的交互&#xff0c;进一步明确对象的职责。有职责链模式、命令模式、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式、策略模式、模板方法模式及访问模式共11种。 1 职责链模式 需求&#xff1a;1) 请求能被多…

如何使用golang自带工具对代码进行覆盖率测试

在 Go 语言中&#xff0c;测试代码覆盖率通常使用 go test 命令结合 -cover 和 -coverprofile 1. 基本代码覆盖率报告 在项目目录下运行以下命令 go test -cover这将在控制台输出一个代码覆盖率的百分比。但是&#xff0c;这种方式不会保存覆盖率数据&#xff08;可以指定目…

18.多分类问题代码实现

在机器学习中&#xff0c;多分类问题是一类常见的问题&#xff0c;它涉及到将输入数据划分为多个类别中的一个。例如&#xff0c;在图像识别中&#xff0c;我们可能需要将图像分为不同的类别&#xff0c;如手写数字识别&#xff08;MNIST数据集&#xff09;就是将手写数字图像分…

反对加征关税,特斯拉上海厂传减产20% | 百能云芯

特斯拉公司首席执行官马斯克近日在公开场合表达了对美国计划对中国电动车加征关税的反对立场&#xff0c;强调特斯拉不支持任何扭曲市场的举措。据知情人士透露&#xff0c;特斯拉上海工厂正计划在今年第二季度至少削减Model Y车型的产量20%&#xff0c;以应对市场需求的变化。…

Linux配置PyTorch GPU环境

本文是基于系统已经安装了驱动和CUDA的&#xff0c;假如不会安装驱动和CUDA的&#xff0c;可以参考我写的上一篇文章&#xff1a;https://blog.csdn.net/pdc31czy/article/details/136072017?spm1001.2014.3001.5501 并且本文是基于HPC写的笔记&#xff0c;普通电脑跳过步骤1…

C#读取.sql文件并执行文件中的sql脚本

有些时候我们需要在程序中编写读取sql脚本文件并执行这些sql语句&#xff0c;但是我们在有些时候会遇到读出来的sql语句不能执行&#xff0c;其实不能执行并不是你的sql脚本文件有错误&#xff0c;而是去执行sql语句的时候&#xff0c;C#代码里面执行sql语句的代码对sql里面的一…

低代码与人工智能:改变软件开发的未来

引言 在当今快速发展的科技时代&#xff0c;软件开发行业也在不断地创新和演进。其中&#xff0c;低代码开发和人工智能技术是两个备受关注的领域&#xff0c;低代码开发通过简化开发流程和降低编码难度&#xff0c;使得软件开发变得更加高效和便捷&#xff0c;而人工智能技术…

正宇软件:引领数字人大新纪元,开启甘肃人大代表履职新篇章

在数字化强国的主旋律之下&#xff0c;政府工作的数字化、智能化转型已成为提升治理效能、增强人民满意度的关键一环。在这个大背景下&#xff0c;正宇软件技术开发有限公司以其卓越的技术实力和丰富的行业经验&#xff0c;成为了政府信息化建设的杰出代表。甘肃省人大代表履职…

基于 Wireshark 分析 TCP 协议

一、TCP 协议 TCP&#xff08;Transmission Control Protocol&#xff09;是一种面向连接的、可靠的传输层协议。它在网络通信中扮演着重要的角色&#xff0c;用于保证数据的可靠传输。 TCP协议的特点如下&#xff1a; 1. 面向连接&#xff1a;在通信前需要先建立连接&#x…

Hunyuan-DiT环境搭建推理测试

引子 最近鹅厂竟然开源了一个多模态的大模型&#xff0c;之前分享福报厂的多模态视觉大模型&#xff08;Qwen-VL环境搭建&推理测试-CSDN博客&#xff09;感兴趣的可以移步。鹅厂开源的&#xff0c;我还是头一回部署。好的&#xff0c;那就让我们看看这个多模态视觉大模型有…

强化学习,第 3 部分:蒙特卡罗方法

文章目录 一、介绍二、关于此文章三、无模型方法与基于模型的方法四、V函数估计4.1 基本概念4.2 V-功能 五、Q 函数估计5.1 V函数概念5.2 优势5.3 Q函数 六、勘探与勘探的权衡七、结论 一、介绍 从赌场到人工智能&#xff1a;揭示蒙特卡罗方法在复杂环境中的强大功能    强化…

企微运营SOP:构建高效、规范的运营流程

随着企业微信在企业内部沟通协作中的广泛应用&#xff0c;如何构建一套高效、规范的企微运营流程成为了众多企业关注的焦点。本文将详细探讨企微运营SOP&#xff08;Standard Operating Procedure&#xff0c;标准操作程序&#xff09;的重要性、构建方法以及实施效果&#xff…

zstd库数据压缩与解压缩

在 Visual Studio 2019 中使用 C 的 zstd 库进行数据压缩与解压缩 在今天的博客中&#xff0c;我们将探讨如何在 Visual Studio 2019 中使用 zstd 库进行高效的数据压缩和解压缩。zstd&#xff08;也称为 Zstandard 或 zstd&#xff09;是由 Facebook 开发的开源压缩库&#x…

动手学深度学习22 池化层

动手学深度学习22 池化层 1. 池化层2. 实现3. QA 课本&#xff1a; https://zh-v2.d2l.ai/chapter_convolutional-neural-networks/pooling.html 视频&#xff1a; https://www.bilibili.com/video/BV1EV411j7nX/?spm_id_fromautoNext&vd_sourceeb04c9a33e87ceba9c9a2e5f0…

CTF_RE周报(五)

这周感觉题目都开始上难度了&#xff0c;很多题都需要很多的基础知识&#xff0c;也是练到哪学到那&#xff0c;所以刷题的速度还是降了一点 angr符号化执行 上上周就已经遇到了&#xff0c;这周一个buu题也是可以用&#xff0c;就开始学学了&#xff0c;目前还差一半 [WUST…