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

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;
}

 【运行结果】

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

sqlserver——查询(四)——连接查询

目录 一.连接查询 分类&#xff1a; 内连接&#xff1a; 1. select ... from A&#xff0c;B &#xff1b; 2. select ..from A&#xff0c;B where ..&#xff1b; 3.select ...,... from A join B on... 4. where 与 join...on 的区别 5. where位置的先后 导语&#xff1…

开发心电疾病分类的深度学习模型并部署运行于ARM虚拟硬件平台(AVH)

目录 一、ARM虚拟硬件平台介绍 二、心电疾病分类模型介绍 三、部署流程 3.1 基于百度云平台订阅虚拟硬件镜像 3.2 安装编译相关组件 3.3 数据加载 3.4 模型转换 方式一&#xff1a; tensorflow模型转换为onnx模型&#xff0c;onnx模型转换为TVM模型 方式二&#xff1…

【操作系统】发展与分类(手工操作、批处理、分时操作、实时操作)

2.操作系统发展与分类 思维导图 手工操作阶段&#xff08;此阶段无操作系统&#xff09; 需要人工干预 缺点&#xff1a; 1.用户独占全机&#xff0c;资源利用率低&#xff1b; 2.CPU等待手工操作&#xff0c;CPU利用不充分。 批处理阶段&#xff08;操作系统开始出现&#x…

从零入门激光SLAM(二十一)——FAST-LIO2论文解析

FAST-LIO2: Fast Direct LiDAR-Inertial Odometry 论文地址&#xff1a;https://ieeexplore.ieee.org/stamp/stamp.jsp?tp&arnumber9697912 代码&#xff1a;https://github.com/hku-mars/FAST_LIO 一、文章概述 1.问题导向 基于视觉传感器的高分辨率和高精度的实时密…

Excel 取出每组最后一行

Excel的前两列是两层的分组列&#xff0c;后两列是明细 ABCD1CM11112CM12123CM13134CM14145CM25156CM26167BM11218BM12229BM232310AM113111AM323212AM333313AM3434 现在要取出每小组的最后一行&#xff1a; ABCD1CM14142CM26163BM12224BM23235AM11316AM3434 使用 SPL XLL sp…

编译原理 期末复习笔记整理(上)

资料借鉴&#xff1a; 【编译原理】期末复习 零基础自学_哔哩哔哩_bilibili 编译原理笔记 第一章 引论 1.编译原理逻辑过程&#xff1a; 词法分析 语法分析 语义分析 中间代码生成 编译代码生成 2.词法分析 任务: 输入源程序&#xff0c;对…

SpringBootWeb 篇-深入了解 Mybatis 删除、新增、更新、查询的基础操作与 SQL 预编译解决 SQL 注入问题

&#x1f525;博客主页&#xff1a; 【小扳_-CSDN博客】 ❤感谢大家点赞&#x1f44d;收藏⭐评论✍ 文章目录 1.0 Mybatis 的基础操作 2.0 基础操作 - 环境准备 3.0 基础操作 - 删除操作 3.1 SQL 预编译 3.2 SQL 预编译的优势 3.3 参数占位符 4.0 基础操作 - 新增 4.1 主键返回…

不拍视频,不直播怎么在视频号卖货赚钱?开一个它就好了!

大家好&#xff0c;我是电商糖果 视频号这两年看着抖音卖货的热度越来越高&#xff0c;也想挤进电商圈。 于是它模仿抖音推出了自己的电商平台——视频号小店。 只要商家入驻视频号小店&#xff0c;就可以在视频号售卖商品。 具体怎么操作呢&#xff0c;需要拍视频&#xf…

Windows下mingw32编译ffmpeg5.1.4实现rtsp拉流

由于客户要求&#xff0c;要在Windows下使用mingw32编译&#xff0c;去ffmpeg.org下载需要编译的版本&#xff0c;使用msys2方法进行编译&#xff0c;使用QT5.10的编译器&#xff0c;基本上把网上的方法试了个遍&#xff0c;编译全部库总是报错出问题 查看了ffbuild文件夹中con…

JSP期末要点复习

一、JSP工作原理 1.客户端请求JSP页面&#xff1a;用户通过浏览器发送一个请求到服务器&#xff0c;请求一个特定的JSP页面。这个请求被服务器上的Web容器&#xff08;如Apache Tomcat&#xff09;接收。 2.JSP转换为Servlet&#xff1a;当JSP页面第一次被请求时&#xff0…

魅族应用市场驳回 安装包包含32位库,请处理32位库后再重新提交

问题出现 解决方法 打开HBuilerX找到项目的mainfest.json 取消cpu类型中armeabi-v7a的勾选。 armeabi-v7a 第7代及以上的ARM处理器&#xff08;ARM32位&#xff09;&#xff0c;市面上大多数手机使用此CPU类型。 arm64-v8a 第8代、64位ARM处理器&#xff08;ARM64位&#x…

用《让子弹飞》的话说,网易希望自己2024年又高又硬

5月23日港股盘后&#xff0c;网易披露了2024年第一季度的财务报告。报告期内&#xff0c;公司总营收达到268.52亿人民币&#xff0c;同比增长7.21%。归母净利润表现强劲&#xff0c;达76.34亿人民币&#xff0c;同比增长13.02%。 结合行业大环境背景来看&#xff0c;尽管去年Q…

Elasticsearch之入门与安装

Elaticsearch&#xff0c;简称为es&#xff0c; es是一个开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检索数据&#xff1b;本身扩展性很好&#xff0c;可以扩展到上百台服务器&#xff0c;处理PB级别的数据。es也使用Java开发并使用Lucene作为其核心来…

六西格玛培训公司:企业成长的“超级导师”——张驰咨询

六西格玛培训公司在企业中扮演着至关重要的角色&#xff0c;其作用主要体现在以下几个方面&#xff1a; 提升企业管理能力&#xff1a; 六西格玛管理将数据和事实作为驱动力&#xff0c;帮助企业将管理从理论转化为实际行动。 通过实施六西格玛管理&#xff0c;企业能够显著…

学习Java的日子 Day49 函数,DOM

Day48 1.流程控制语句 if else for for-in(遍历数组时&#xff0c;跟Java是否一样) While do while break 语句用于跳出循环 continue 用于跳过循环中的一个迭代 2.函数 2.1 JavaScript 函数语法 函数就是包裹在花括号中的代码块&#xff0c;前面使用了关键词 function funct…

信息系统项目管理师0133:工具与技术(8项目整合管理—8.8实施整体变更控制—8.8.2工具与技术)

点击查看专栏目录 文章目录 8.8.2 工具与技术8.8.2 工具与技术 专家判断实施整体变更控制过程中,应征求具备如下领域相关专业知识或接受过相关培训的个人或小组的意见,涉及领域包括:关于项目所在的行业以及项目关注的领域的技术知识;法律法规;法规与采购;配置管理;风险管…

HTTP 协议的基本格式和Fidder的简单使用

HTTP协议诞生于1996&#xff08;开玩笑哈&#xff0c;诞生于1991年&#xff09;&#xff0c;http协议用于网页和手机app和服务器交互的场景。通过HTTP协议&#xff0c;客户端&#xff08;例如网页浏览器或手机应用&#xff09;可以向服务器发送请求&#xff0c;服务器则会响应这…

简单微信企业群消息推送接口

群管理 群发送接口 POST: JSONURL http://localhost:65029/m/wxapi/sendwxmsg{ "nr":"试", --消息 "at":"wxid_y0k4dv0xcav622,wxid_y0k4dv0xcav622",--群wxid "key":"F98F354F1671A2D21BC78C76B95E96EB",--群k…

振弦采集仪在岩土工程监测中的精度与可靠性评估

振弦采集仪在岩土工程监测中的精度与可靠性评估 河北稳控科技振弦采集仪是一种常用的岩土工程土体力学参数监测仪器&#xff0c;它主要用于测量岩土中的应力、应变和模量等力学参数。在岩土工程中&#xff0c;土体力学参数的精确测量对于工程设计、施工和监测都非常重要。因此…

python-编写函数判断一个三位数是否为水仙花数。

【问题描述】要求编写函数isflower(n)判断一个三位数n是否为水仙花数,如果是&#xff0c;则返回True&#xff0c;否则返回False。在主程序中要求调用该函数并输出三位数中所有的水仙花数。所谓"水仙花数"是指一个3位数&#xff0c;其各位数字立方和等于该数本身。例如…