多线程+互斥+条件变量题目

在这里插入图片描述

欢迎来到Cefler的博客😁
🕌博客主页:折纸花满衣
🏠个人专栏:题目解析

在这里插入图片描述


目录

  • 👉🏻 完成两个线程通过条件变量实现交替打印
    • 错误代码加优化(c++线程库版本)
    • 版本2(使用phtread.h库)
  • 👉🏻按序打印
  • 👉🏻 H2O 生成

👉🏻 完成两个线程通过条件变量实现交替打印

1.题目描述:线程A打印-我是线程A;线程B打印-我是线程B; 最终实现交替打印,不能出现连续的相同打印。

2.本题主要考察条件变量的基本使用流程

错误代码加优化(c++线程库版本)

#include<iostream>
#include<mutex>
#include<thread>
#include<condition_variable>
#include<unistd.h>using namespace std;
mutex mx;//互斥锁
condition_variable cv;//条件变量bool flag = true;
void Print(char args)
{char c = static_cast<char>(args);for (int i = 0; i < 5; i++){unique_lock<mutex> lock(mx); // 上锁//if(!flag)cv.wait(lock,[]{return flag;}); // 等待条件 flag 为 true[]{return flag||!flag;}if(c=='A')cout << "我是线程A" << endl;else if(c=='B')cout<<"我是线程B"<<endl;flag = !flag;cv.notify_one(); // 通知另一个线程sleep(1);}
}
int main()
{//创建AB线程std::thread threadA(Print,'A');std::thread threadB(Print,'B');// 等待线程结束threadA.join();threadB.join();return 0;
}

在这里插入图片描述
此代码会导致第一次打印字符A后就阻塞不动了,
主要原因出在这行代码上

cv.wait(lock,[]{return flag;}); 

wait的第二个参数是个函数对象(这里是lamda表达式),当返回值是false时,wait会进行阻塞,true时,wait会开始释放锁,当前线程拿到锁后开始继续执行。
因为flag一开始为true,所以此时线程A是拿到锁并执行打印工作的。
而后将flag改为false,并去唤醒线程B(唤醒它来看看wait是否满足情况了),此时第二次循环进来,线程A会被wait阻塞住。
而线程B这边已经苏醒,过来第一次循环,结果被阻塞,这是怎么回事?因为flag被改为false了,所以线程B阻塞了,而此时线程A同时也被阻塞,直接导致两个线程统统被阻塞,所以这个wait的判定条件是个大问题。
要解决的话就是将线程A和线程B进来的不同情况都要考虑进去。

代码优化如下:

#include<iostream>
#include<mutex>
#include<thread>
#include<condition_variable>
#include<unistd.h>using namespace std;
mutex mx;//互斥锁
condition_variable cv;//条件变量bool flag = true;
void Print(char args)
{char c = static_cast<char>(args);for (int i = 0; i < 5; i++){unique_lock<mutex> lock(mx); // 上锁cv.wait(lock,[&]{return c=='A'&&flag||c=='B'&&!flag;}); // 等待条件 flag 为 true[]{return flag||!flag;}cout<<"我是线程"<<c<<endl;flag = !flag;cv.notify_one(); // 通知另一个线程sleep(1);}
}int main()
{//创建AB线程std::thread threadA(Print,'A');std::thread threadB(Print,'B');// 等待线程结束threadA.join();threadB.join();return 0;
}

在这里插入图片描述

版本2(使用phtread.h库)

#include<iostream>
#include<pthread.h>
#include<unistd.h>
using namespace std;//声明互斥锁和条件变量
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;bool flag = false;
void* Print(void* args)
{char c = *(static_cast<char*>(args));for(int i = 0;i<5;i++){//先上锁为敬pthread_mutex_lock(&mtx);//判断条件变量while(c=='A'&&flag||c=='B'&&!flag){pthread_cond_wait(&cv,&mtx);//线程阻塞,等待唤醒}cout<<"我是线程"<<c<<endl;flag = !flag;sleep(1);pthread_cond_signal(&cv);//唤醒其它线程pthread_mutex_unlock(&mtx);//解锁,当其它线程被唤醒时能拿到锁}return nullptr;
}
int main()
{//1.线程声明pthread_t threadA,threadB;char c1 = 'A',c2 = 'B';//2.创建线程pthread_create(&threadA,nullptr,Print,(void*)&c1);pthread_create(&threadB,nullptr,Print,(void*)&c2);//3.线程等待回收pthread_join(threadA,nullptr);pthread_join(threadB,nullptr);//4.互斥锁和条件变量销毁pthread_mutex_destroy(&mtx);pthread_cond_destroy(&cv);return 0;
}

这里有几个需要注意的要点:
1.pthread_create中的线程函数返回值必须是void类型的,参数为void,也就是指针类型

2.使用 while 循环则可以避免虚假唤醒的问题。当线程被唤醒时,它会重新检查条件是否满足。如果条件不满足,线程将继续等待,直到条件满足为止。这样可以确保线程在接收到正确的信号时才会继续执行。

👉🏻按序打印

原题链接:按序打印

mycode:


class Foo {
mutex mtx;
condition_variable cv;
int num = 0;
public:Foo() {}void first(function<void()> printFirst) {// printFirst() outputs "first". Do not change or remove this line.unique_lock<mutex> lock(mtx);cv.wait(lock,[&]{return num==0;});printFirst();num = (num+1)%3;cv.notify_all();//唤醒全部线程}void second(function<void()> printSecond) {// printSecond() outputs "second". Do not change or remove this line.//上锁unique_lock<mutex> lock(mtx);cv.wait(lock,[&]{return num==1;});printSecond();num = (num+1)%3;cv.notify_one();//唤醒一个线程}void third(function<void()> printThird) {// printThird() outputs "third". Do not change or remove this line.unique_lock<mutex> lock(mtx);cv.wait(lock,[&]{return num==2;});printThird();num = (num+1)%3;//cv.notify_one();//唤醒一个线程}
};

这里要注意的是唤醒线程只需要一个notify_all和notify_one就行了,这样就只会执行3次操作而已,不会过多导致时间超时
为什么呢?因为不管哪个函数先进入,如果因为条件不满足,会堵塞在那里,等待被唤醒,一个notify_all先将其余两个线程唤醒,此时这两个线程过来查看条件变量情况,一个会成功,一个会失败阻塞,这个时候还差一个线程还没执行完全在等待,就再来一个notify_one唤醒即可。

👉🏻 H2O 生成

原题链接:H2O 生成

mycode:

int num_h = 0;
class H2O {
mutex mtx;
condition_variable cv;
public:H2O() {}void hydrogen(function<void()> releaseHydrogen) {// releaseHydrogen() outputs "H". Do not change or remove this line.unique_lock<mutex> lock(mtx);cv.wait(lock,[&]{return num_h<2;});//H的数量要小于2releaseHydrogen();++num_h;cv.notify_all();//唤醒氧线程}void oxygen(function<void()> releaseOxygen) {// releaseOxygen() outputs "O". Do not change or remove this line.unique_lock<mutex> lock(mtx);cv.wait(lock,[&]{return num_h==2;});num_h = 0;//H与O匹配消耗完后清空releaseOxygen();cv.notify_all();//唤醒氢气线程}
};

如上便是本期的所有内容了,如果喜欢并觉得有帮助的话,希望可以博个点赞+收藏+关注🌹🌹🌹❤️ 🧡 💛,学海无涯苦作舟,愿与君一起共勉成长

在这里插入图片描述
在这里插入图片描述

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

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

相关文章

蓝桥杯每日一题:约数个数(质因数)

题目描述&#xff1a; 输入 n 个整数&#xff0c;依次输出每个数的约数的个数。 输入格式 第一行包含整数 n。 第二行包含 n 个整数 ai。 输出格式 共 n 行&#xff0c;按顺序每行输出一个给定整数的约数的个数。 数据范围 1≤n≤1000, 1≤ai≤10^9 输入样例&#xff…

机器学习知识点全面总结

机器学习按照模型类型分为监督学习模型、无监督学习模型两大类。 1、有监督学习 有监督学习通常是利用带有专家标注的标签的训练数据&#xff0c;学习一个从输入变量X到输入变量Y的函数映射。Y f (X)&#xff0c;训练数据通常是(nx,y)的形式&#xff0c;其中n代表训练样本的大…

ARM汇编与逆向工程:揭秘程序背后的神秘世界

文章目录 一、ARM汇编语言&#xff1a;底层世界的密码二、逆向工程&#xff1a;软件世界的侦探工作三、ARM汇编与逆向工程的完美结合四、ARM汇编逆向工程的风险与挑战五、ARM汇编逆向工程的未来展望《ARM汇编与逆向工程 蓝狐卷 基础知识》内容简介作者简介译者简介ChaMd5安全团…

C语言第四十弹---预处理(下)

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 预处理 1、#和## 1.1 #运算符 1.2、##运算符 2、命名约定 3、#undef 4、命令行定义 5、条件编译 6、头文件的包含 6.1、头文件被包含的方式 6.1.1、本地…

力扣面试150: O(1) 时间插入、删除和获取随机元素 HashMap结合数组

Problem: 380. O(1) 时间插入、删除和获取随机元素 文章目录 思路复杂度Code 思路 &#x1f469;‍&#x1f3eb; 三叶题解 复杂度 时间复杂度: O ( 1 ) O(1) O(1) 空间复杂度: O ( n ) O(n) O(n) Code class RandomizedSet {static int[] nums new int[200_010];//存…

基于kmeans的聚类微博舆情分析系统

第一章绪论 1.1研究背景 如今在我们的生活与生产的每个角落都可以见到数据与信息的身影。自从上十世纪八十年代的中后期开始&#xff0c;我们使用的互联网技术已经开始快速发展&#xff0c;近些年来云计算、大数据和物联网等与互联网有相领域的发展让互联网技术达到了史无前例…

1、java语法入门(找工作版)

文章目录 一、Java简介二、Java常量与变量1、标识符2、关键字3、变量4、类的命名规则5、数据类型6、基本数据类型字面值7、变量的定义与初始化8、ASCII码和Unicode编码9、转义字符10、类型转换11、常量 三、Java运算符1、算术运算符2、赋值运算符3、关系运算符4、逻辑运算符5、…

电子积木方案开发商

东莞市酷得智能科技有限公司电子积木方案开发商 提供消费电子解决方案、提供IC技术支持&#xff0c;全国线上线下服务 积木小车底层驱动开发过程主要涉及到以下几个方面&#xff1a; 首先&#xff0c;需要对小车底盘结构、硬件、模块等有深入的了解。底盘承载着机器人定位、导…

C++——STL容器——string

目录 1.构造函数 模拟实现 2.析构函数 模拟实现 3.string遍历 3.1 c_str、size、lenth、capacity等 模拟实现 3.2 字符串元素访问 3.2.1 []操作符重载、at 模拟实现 3.2.2 front、back等 3.3 迭代器 模拟实现 4.赋值操作 4.1 赋值重载函数 模拟实现 4.2 assig…

如何保证全部流量走代理

最近因为某些原因&#xff0c;需要做一些确保高匿的事情&#xff0c;便花时间做了一定的调研&#xff0c;至于是什么事情这里不便多说。 本文主要还是聊聊我看到的一些使用代理软件误区和确保流量全部走代理的方法&#xff0c;甚至也可以说是Proxifier的用户使用手册&#xff…

吴恩达2022机器学习专项课程(一) 5.4 多元线性回归的梯度下降

问题预览/关键词 多元线性回归的函数是&#xff1f;如何向量化表达&#xff1f;如何计算多元线性回归的成本函数的梯度&#xff1f;正规方程法是什么&#xff1f;正轨方程法的缺点是什么&#xff1f; 笔记 1.多元线性回归函数 5.1章节描述过。 向量化函数 原版函数 2.计…

Redis中的持久化

持久化 .RDB手动触发save命令bgsave命令 自动触发bgsave的具体流程RDB的处理保存压缩校验 RDB的优缺点 AOF命令写入文件同步重写机制启动时恢复数据 本章重点回顾 . RDB RDB持久化是把当前进程数据生成快照保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发 手动触发…

特朗普数字钱包被空投100万MVP,加密资产或将提供更多竞选资金

唐纳德.特朗普先生对待加密货币的态度正在发生改变&#xff0c;曾经他对加密货币持有负面的态度&#xff0c;曾多次在公开场合批评比特币等数字货币。然而&#xff0c;随着特朗普NFT等加密资产的上链&#xff0c;他对加密货币的态度也发生了巨大的转变。 据相关媒体报道&#x…

FastWiki发布`0.2.4`支持js 函数

Release v0.2.4 AIDotNet/fast-wiki (github.com) 支持JS动态functioncall调用支持动态function管理支持JS在线编辑提供智能代码提示支持JS在线编辑提供部分绑定的c#类&#xff08;默认提供Console&#xff0c;HttpClient&#xff09;支持Application绑定多个Function Call优…

地面站Mission Planner从源码编译与运行

0. 环境 - win10&#xff08;基本需要100G硬盘&#xff09; - ubuntu18 1. 安装vs2022 下载 vs2022 community 在线安装包。 https://visualstudio.microsoft.com/ 打开 Visual Studio Installer 先安装 Visual Studio Community 2022本体。占用1.2GB。 Visual Studio Inst…

【Docker系列】在 Linux 上安装 Docker Compose 的简明步骤

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Git 如何去使用

目录 1. Git暂存区的使用 1.1. 暂存区的作用 1.2. 暂存区覆盖工作区&#xff08;注意&#xff1a;完全确认覆盖时使用&#xff09; 1.3. 暂存区移除文件 1.4. 练习 2. Git回退版本 2.1. 概念 2.2. 查看提交历史 2.3. 回退命令 2.4. 注意 3. Git删除文件 3.1. 需求 …

CAN的回环测试实验

我只有一个STM32F429的开发板,所以这次我就做个回环测试. 1.先了解一下有关CAN的一些标准库,结构体 1.CAN初始化结构体---CAN_InitTypeDef 2.CAN发送及接收结构体--- CanTxMsg(发送结构体) CanRxMsg(接收结构体) 3.CAN筛选器结构体 --- CAN_FilterInitTypeDef 2.代码编写 以及…

HarmonyOS 和 OpenHarmony

HarmonyOS 和 OpenHarmony 支持的 shell 命令不同&#xff0c;因此有时候需要做一做区分&#xff0c;目前有些文档上没有标注&#xff0c;因此可能产生歧义。 HarmonyOS 支持 getprop&#xff1a; getprop hw_sc.build.os.apiversion # 查看API版本OpenHarmony 上支持 param…

SYS-2722音频分析仪SYS2722

181/2461/8938产品概述&#xff1a; Audio Precision 2722 音频分析仪是 Audio Precision 屡获殊荣的 PC 控制音频分析仪的旗舰型号&#xff0c;长期以来一直是音频设备设计和测试的全球公认标准。功能齐全的 SYS-2722 提供了测试转换器技术最新进展所需的无与伦比的失真和噪声…