操作系统实验:进程和线程同步和互斥(生产者消费者问题,睡觉的理发师问题)

1.生产者消费者问题(信号量)

参考教材中的生产者消费者算法,创建5个进程,其中两个进程为生产者进程,3个进程为消费者进程。一个生产者进程试图不断地在一个缓冲中写入大写字母,另一个生产者进程试图不断地在缓冲中写入小写字母。3个消费者不断地从缓冲中读取一个字符并输出。为了使得程序的输出易于看到结果,仿照的实例程序,分别在生产者和消费者进程的合适的位置加入一些随机睡眠时间。

可选的实验:在上面实验的基础上实现部分消费者有选择地消费某些产品。例如一个消费者只消费小写字符,一个消费者只消费大写字母,而另一个消费者则无选择地消费任何产品。消费者要消费的产品没有时,消费者进程被阻塞。注意缓冲的管理。

【参考代码】 

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <random>
using namespace std;const int n = 10; // 缓冲区大小
queue<char> buffer; // 缓冲区
mutex mtx; // 互斥锁
condition_variable empty, da, xiao; // 条件变量
int flag = -1; // 标志位// 生产者线程A,生成大写字符
void produce_A() 
{while (true) {unique_lock<std::mutex> lock(mtx);empty.wait(lock, [] { return buffer.size() < n; }); // 等待缓冲区非满char ch = 'A' + std::rand() % 26; // 生成大写字符buffer.push(ch); // 将字符放入缓冲区da.notify_one(); // 通知消费者有大写字符可用sleep(1);}
}
// 生产者线程a,生成小写字符
void produce_a() 
{while (true) {unique_lock<std::mutex> lock(mtx);empty.wait(lock, [] { return buffer.size() < n; }); // 等待缓冲区非满char ch = 'a' + std::rand() % 26; // 生成小写字符buffer.push(ch); // 将字符放入缓冲区xiao.notify_one(); // 通知消费者有小写字符可用sleep(1);}
}
// 消费者线程A,处理大写字符
void consumer_A() 
{while (true) {unique_lock<std::mutex> lock(mtx);da.wait(lock, [] { return !buffer.empty(); }); // 等待有大写字符可用char ch = buffer.front(); // 从缓冲区取出字符buffer.pop(); // 移除字符empty.notify_one(); // 通知生产者缓冲区有空位cout << "Consumer A: " << ch << std::endl; // 输出字符sleep(1);}
}
// 消费者线程a,处理小写字符
void consumer_a() 
{while (true) {unique_lock<std::mutex> lock(mtx);xiao.wait(lock, [] { return !buffer.empty(); }); // 等待有小写字符可用char ch = buffer.front(); // 从缓冲区取出字符buffer.pop(); // 移除字符empty.notify_one(); // 通知生产者缓冲区有空位cout << "Consumer a: " << ch << std::endl; // 输出字符sleep(1);}
}
// 消费者线程A或a,处理大写或小写字符
void consumer_A_or_a()
{while (true) {unique_lock<std::mutex> lock(mtx);da.wait(lock, [] { return !buffer.empty(); }); // 等待有大写字符可用char ch = buffer.front(); // 从缓冲区取出字符buffer.pop(); // 移除字符empty.notify_one(); // 通知生产者缓冲区有空位cout << "Consumer A or a: " << ch << std::endl; // 输出字符sleep(1);}
}int main()
{thread producerA(produce_A);thread producera(produce_a);thread consumerA(consumer_A);thread consumera(consumer_a);thread consumerAora(consumer_A_or_a);producerA.join();producera.join();consumerA.join();consumera.join();consumerAora.join();return 0;
}

【运行结果】

1、竞争不是很明显 2、某些进程消费了错误的产品

2.实现睡觉的理发师问题(同步互斥方式采用信号量或mutex方式均可)

理发师问题的描述:一个理发店接待室有n张椅子,工作室有1张椅子;没有顾客时,理发师睡觉;第一个顾客来到时,必须将理发师唤醒;顾客来时如果还有空座的话,他就坐在一个座位上等待;如果顾客来时没有空座位了,他就离开,不理发了;当理发师处理完所有顾客,而又没有新顾客来时,他又开始睡觉。

【参考代码】 线程实现睡觉的理发师问题(mutex方式)icon-default.png?t=N7T8http://t.csdnimg.cn/JNRne

#include <bits/stdc++.h>
#include <pthread.h>
#include <unistd.h>
using namespace std;pthread_mutex_t Mutex;
int n;
int num;
int flag = -1;void *customer(void *arg)
{while(flag){pthread_mutex_lock(&Mutex);if(num < n){num++;cout << "A customer IN, chairs left:" << n - num << endl;pthread_mutex_unlock(&Mutex); //解锁}else{pthread_mutex_unlock(&Mutex); //解锁cout << "No chairs!" << endl;}}
}void *barber(void *arg){while(flag){if(num > 0){pthread_mutex_lock(&Mutex);num--;cout << "A customer OUT, chairs left:" << n-num << endl;pthread_mutex_unlock(&Mutex); //解锁}}
}int main()
{cout << "input chairs number:" << endl;cin>>n;num = 0;pthread_t Barber, Customer;pthread_mutex_init(&Mutex, NULL);pthread_create(&Barber, NULL, barber, NULL);pthread_create(&Customer, NULL, customer, NULL);sleep(1);flag = 0;pthread_join(Barber, NULL);pthread_join(Customer, NULL);pthread_mutex_destroy(&Mutex);return 0;
}

 【运行结果】

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

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

相关文章

OrangePi Kunpeng Pro开发板初体验——家庭小型服务器

引言 在开源硬件的浪潮中&#xff0c;开发板作为创新的基石&#xff0c;正吸引着全球开发者的目光。它们不仅为技术爱好者提供了实验的平台&#xff0c;更为专业开发者带来了实现复杂项目的可能性。本文将深入剖析OrangePi Kunpeng Pro开发板&#xff0c;从开箱到实际应用&…

vue3父子组件通信,子组件修改父组件传过来的值

一、第一种&#xff0c;通过props方式传值&#xff1a; 父组件&#xff1a; 父组件调用子组件Child1时通过 :msg2 "msg2"把msg2的数据传给子组件&#xff0c;并且通过自定义事件接收子组件的emit通知&#xff0c;用来修改父组件的msg2数据。 源码&#xff1a; &l…

融资融券操作指南(附最低费率开户渠道)

部分朋友在开通融资融券后&#xff0c;对于融资融券的操作不是很熟练&#xff0c;并且存在很多问题。其实&#xff0c;融资融券核心就是一个“借”&#xff0c;你借券商的资金或者股票&#xff0c;看多时借入资金买入&#xff0c;看空时借入券源卖出。你不可能空口白牙的去借&a…

如何画泳道图?

一、绘制泳道图 1、新建一个绘图&#xff0c; 工具箱搜索“泳道图” 2、修改泳道图标题及风格 3、绘制基本的流程图 4、导出Visio格式 选择文件导出&#xff0c;visio格式

安全工程师考试摸拟试题

安全工程师考试摸拟试题安全工程师是指在工程项目中负责安全管理和安全技术服务的专业人员。他们需要具备扎实的理论知识和丰富的实践经验&#xff0c;能够有效预防和控制各类安全风险… 1 安全工程师考试摸拟试题 安全工程师是指在工程项目中负责安全管理和安全技术服务的专业…

实战14:粒子群算法pso优化机器学习集成学习进行数据预测-完整代码数据

视频演示: 效果演示: 主要代码: import numpy as np from sklearn.model_selection import train_test_split from sklearn.ensemble import GradientBoostingRegressor, AdaBoostRegressor from xgboost import XGBRegressor from lightgbm import LGBMRegressor from s…

MySQL|主从复制配置

我使用的是两个云服务器&#xff0c;如果读者使用的是虚拟机和本机&#xff0c;配置会简单很多。 关于云服务器安全组设置、防火墙端口等问题请参考文章&#xff1a; 使用华为云服务器进行项目部署&#xff08;云服务器、防火墙配置&#xff09; 条件&#xff1a;master 和 s…

SaaS增长三大策略:从用户获取到留存转化的全链路解析

在SaaS&#xff08;软件即服务&#xff09;行业中&#xff0c;增长是企业成功的关键。然而&#xff0c;要实现持续增长并非易事&#xff0c;需要一套从用户获取到留存转化的全链路策略。 首先&#xff0c;用户获取是SaaS增长的第一步。 这要求企业明确目标用户群体&#xff0…

【LeetCode】【9】回文数(1047字)

文章目录 [toc]题目描述样例输入输出与解释样例1样例2样例3 提示进阶Python实现 个人主页&#xff1a;丷从心 系列专栏&#xff1a;LeetCode 刷题指南&#xff1a;LeetCode刷题指南 题目描述 给一个整数x&#xff0c;如果x是一个回文整数&#xff0c;返回true&#xff1b;否…

C# VSTO读取Excel单元格Value、Value2

对单个单元格的值&#xff0c;需要用object 对象去接 object value (object)oneCellRange.Value; object value2 (object)oneCellRange.Value2; 对矩形范围的值&#xff0c;需要用object[,]去接 object[,] matrixValues (object[,])matrixRange.Value; object[,] matrixV…

【NumPy】关于numpy.sort()函数,看这一篇文章就够了

&#x1f9d1; 博主简介&#xff1a;阿里巴巴嵌入式技术专家&#xff0c;深耕嵌入式人工智能领域&#xff0c;具备多年的嵌入式硬件产品研发管理经验。 &#x1f4d2; 博客介绍&#xff1a;分享嵌入式开发领域的相关知识、经验、思考和感悟&#xff0c;欢迎关注。提供嵌入式方向…

MongoDB数据库清理策略: 自动化过期数据删除实战

1、引言 随着应用程序和业务数据的持续增长&#xff0c;有效地管理数据库存储空间成为维护系统性能的关键。在MongoDB这类NoSQL数据库中&#xff0c;定期清理过期数据变得尤为重要&#xff0c;这不仅能释放宝贵的存储资源&#xff0c;还能优化查询性能&#xff0c;确保数据库运…

Qt 对话框或者QMainWindow等类中调用自定义QWidget继承组件

简单的方法如下所示 1、创建一个ui文件&#xff0c;界面布局放入QVBoxLayout或者QHBoxLayout 使用他来放入自定义组件&#xff0c;类似如下 2、代码如下&#xff1a; ui.setupUi(this); { //自定义组价如下 KwTable *Table new KwTable(this); ui.vertical…

为什么要有NOC

如果是AHB&#xff0c;注意AXI并不真的定义了总线&#xff0c;更多是接口。 那么如何实现上面的带宽&#xff0c;延迟需求呢。 在异构&#xff0c;多时钟&#xff1b;大芯片&#xff0c;物理面积很大&#xff0c;延迟太长&#xff1b;片上系统&#xff0c;IP众多&#xff0c;总…

包装设计的七个秘诀

大家都知道&#xff0c;包装设计的好与坏不等于企业的好&#xff0c;但是消费者会有先入为主的想法&#xff0c;如果一个企业连包装设计都不重视&#xff0c;那么谁来重视产品质量呢&#xff1f;无可否认&#xff0c;对产品的评价首先是质量&#xff0c;但质量之后&#xff0c;…

【OpenVINO™】在C#中使用 OpenVINO™ 部署 YOLOv10 模型实现目标

文章目录 1. 前言1.1 OpenVINO™ C# API1.2 YOLOv10 2. 模型获取2.1 源码下载2.2 配置环境2.3 下载模型 3. Yolov10 项目配置3.1 项目创建与环境配置3.2 定义模型预测方法3.2.1 定义目标检测模型方法3.2.2 使用OpenVINO™ 预处理接口编译模型 3.2 模型预测方法调用 4. 项目运行…

文心智能体之情感领航员:你的智能情感导师

文章目录 引言情感领航员的诞生与定位情感领航员的优势与特点专业性个性化便捷性隐私保护 如何创建自己的智能体创建方式智能体名称和设定基础配置角色与目标指导原则限制澄清个性化 高级配置保存 /发布流量数据分析智能体调优 总结 引言 在现代社会中&#xff0c;情感问题的普…

[CISCN2024]-PWN:orange_cat_diary(glibc2.23.,仅可修改最新堆块,house of orange)

查看保护 查看ida 这里我们仅可以修改最新申请出来的堆块&#xff0c;但是有uaf漏洞。 完整exp&#xff1a; from pwn import* #context(log_leveldebug) pprocess(./orange) free_got0x201F78def alloc(size,content):p.sendlineafter(bPlease input your choice:,b1)p.send…

行转列——kettle开发14

一、行转列 如图所示&#xff0c;行转列就是把数据字段的字段名转换为一列&#xff0c;把数据行变成数据列。即我们将昨天输出的张三在周一至周日的工作小时转换为7行数据。对应7行数据分别为张三在周一工作多个小时&#xff0c;在周二工作多少个小时等等。 我们来看下行转列组…

pycharm打开服务器(linux)上的项目

先在本地打开项目 一、项目文件配置 tools-deployment-configuration 新增一个sftp连接 测试服务器是否可以连通 mappings中设置本地路径和服务器上的路径 二、环境配置 先参考文章 复现论文的conda环境&#xff08;win和联网、离线linux&#xff09;_conda复现环境-CSDN博…