实验报告 生产者――消费者问题算法的实现(cpp)

2023-05-16

问题的提出:

生产者-消费者(producer-consumer)问题是一个著名的进程同步问题。它描述的是:有一群生产者进程在生产产品,并将这些产品提供给消费者进程去消费。为使生产者进程与消费者进程能并发执行,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将其所生产的产品放入一个缓冲区中;消费费者进程可从一个缓冲区中取走产品去消费。尽管所有的生产者进程和消费者进程都是以异步方式运行的,但它们之间必须保持同步,既不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满产品且尚未被取走的缓冲区中投放产品。

目录

一、预备知识

1、进程管理

2、互斥量

二、目的

1.了解信号量的使用。

2.加深对信号量机制的理解。

三、要求 

1.理解生产者与消费者问题模型,掌握解决该问题的算法思想。

2.掌握正确使用同步机制的方法。

四、实验内容

1.问题描述

2.功能要求

 五、实现代码

运行结果

​编辑

 参考文献


一、预备知识

1、进程管理

进程:进程是指一个具有一定独立功能的程序在一个数据集合上的一次动态执行过程

进程管理:操作系统的职能之一,主要是对处理机进行管理。为了提高CPU的利用率而采用多道程序技术。通过进程管理来协调多道程序之间的关系,使CPU得到充分的利用。

2、互斥量

互斥量(mutex)是c++中提供的一个类,就像一把锁,当有人使用某个资源时,就将锁锁上,使用完毕就将锁打开。

二、目的

1.了解信号量的使用。

2.加深对信号量机制的理解。

三、要求 

1.理解生产者与消费者问题模型,掌握解决该问题的算法思想。

2.掌握正确使用同步机制的方法。

四、实验内容

1.问题描述

一组生产者向一组消费者提供消息,它们共享一个有界缓冲池,生产者向其中投放消息,消费者从中取得消息。假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将消息送入缓冲池,只要缓冲池未空,消费者可从缓冲池取走一个消息。

2.功能要求

根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放数据、取数据等过程。

 五、实现代码

#include<thread>
#include<iostream>
#include<mutex>
#include<list>
#include<vector>

using namespace std;

int exit_thread = 0;//执行完的线程数目
const int producer_int = 10;//生产者数量
const int consumer_int = 10;//消费者数量
list<int>buffer;//这里用int 类型代替要生产的东西(类似于编号)
mutex public_mutex;//缓冲池互斥信号量
//防止producer生产到一半时consumer就访问读取导致数据损坏

void producer()//模拟生产者进程
{
	mutex producer_mutex;//生产者内部互斥量
	//unique_lock<mutex>a(producer_mutex, defer_lock);
	//unique_lock<mutex>b(public_mutex, defer_lock);
	int m;
	//if (a.try_lock() && b.try_lock())
	//{
	lock(producer_mutex, public_mutex);
	lock_guard<mutex>a(producer_mutex, adopt_lock);
	lock_guard<mutex>b(public_mutex, adopt_lock);
	cout << "**************************" << endl;
	cout << "现在运行的消费者线程id是:" << this_thread::get_id() << endl;
	cout << "请输入你要生产的产品编号:";
	cin >> m;
	if (buffer.size() != 10)
	{
		buffer.push_back(m);
		cout << "**************************" << endl;
		cout << "当前缓冲池的情况如下:" << endl;
		for (auto i = buffer.begin(); i != buffer.end(); ++i)
		{
			cout << *i << endl;
		}
		cout << "**************************" << endl;
		exit_thread++;
		//producer_mutex.unlock();
		//public_mutex.unlock();
		return;
	}
	else
	{
		cout << "缓冲池已经满了无法生产东西" << endl;
		cout << "**************************" << endl;
		cout << "当前缓冲池的情况如下:" << endl;
		for (auto i = buffer.begin(); i != buffer.end(); ++i)
		{
			cout << *i << endl;
		}
		cout << "**************************" << endl;
		exit_thread++;
		//producer_mutex.unlock();
		//public_mutex.unlock();
		return;
	}
	//}
}



void consumer()//模拟消费者进程
{
	mutex consumer_mutex;
	//unique_lock<mutex>a(consumer_mutex, defer_lock);
	//unique_lock<mutex>b(public_mutex, defer_lock);
	//if (a.try_lock() && b.try_lock())
	//{
	lock(consumer_mutex, public_mutex);
	lock_guard<mutex>a(consumer_mutex, adopt_lock);
	lock_guard<mutex>b(public_mutex, adopt_lock);
	cout << "**************************" << endl;
	cout << "现在运行的消费者线程id是:" << this_thread::get_id() << endl;
	if (buffer.size() != 0)
	{
		cout << "读取的数据为:" << buffer.front() << endl;
		buffer.pop_front();
		cout << "**************************" << endl;
		cout << "当前缓冲池的情况如下:" << endl;
		for (auto i = buffer.begin(); i != buffer.end(); ++i)
		{
			cout << *i << endl;
		}
		cout << "**************************" << endl;
		exit_thread++;
		//consumer_mutex.unlock();
		//public_mutex.unlock();
		return;
	}
	else
	{
		cout << "缓冲池没有任何产品无法读取产品!!" << endl;
		cout << "**************************" << endl;
		cout << "当前缓冲池的情况如下:" << endl;
		for (auto i = buffer.begin(); i != buffer.end(); ++i)
		{
			cout << *i << endl;
		}
		cout << "**************************" << endl;
		exit_thread++;
		//consumer_mutex.unlock();
		//public_mutex.unlock();
		return;
	}
	//}
}

void displaybuffer()//显示缓冲池情况
{
	cout << "当前缓冲池的情况如下:" << endl;
	for (auto i = buffer.begin(); i != buffer.end(); ++i)
	{
		cout << *i << endl;
	}
	cout << "**************************" << endl;
}

int main()
{
	//vector<thread>t_producer;
	thread t_producer[producer_int];
	//vector<thread>t_consumer;
	thread t_consumer[consumer_int];
	for (int i = 0; i < producer_int; ++i)
	{
		t_producer[i] = thread(producer);
		t_producer[i].detach();
	}
	for (int i = 0; i < consumer_int; ++i)
	{
		t_consumer[i] = thread(consumer);
		t_consumer[i].detach();
	}
	while (1)//防止detach后的进程在主函数结束后还没结束导致异常
	{
		if (exit_thread == (producer_int + consumer_int))
			break;
	}

	displaybuffer();
	cout << "实验完成" << endl;

	return 0;
}


运行结果

 参考文献

1、百度文库

2、具体的线程知识可以观看这个网站学习 

这个程序可能有点简陋,漏洞有点多,各位大佬如果有什么指正的地方可以在评论区指出,谢谢!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

实验报告 生产者――消费者问题算法的实现(cpp) 的相关文章

  • Response.Redirect 打开新窗口的两种方法

    一般情况下 xff0c Response Redirect 方法是在服务器端进行转向 xff0c 因此 xff0c 除非使用 Response Write 34 lt script gt window location 61 39 http
  • C# 实现向浏览器的兼容性视图列表中添加、删除网站和检查网站是否在兼容性网站列表中

    今天回答论坛上的一个问题 xff0c 搜索了一下网上 xff0c 并没有找到一个完整的例子 xff0c 下面根据网上的一些资料 xff0c 经过转换 完善成一个完整的例子 下面的例子可以实现添加 删除 检测网站是否在兼容性网站列表中的功能
  • Excel中 ColorIndex 属性值和颜色对照表

    Excel中 ColorIndex 属性值和颜色对照表 资料参考 http msdn microsoft com en us library cc296089 aspx http www mvps org dmcritchie excel
  • AJAX(XMLHttpRequest)进行跨域请求方法详解(一)

    注意 xff1a 以下代码请在Firefox 3 5 Chrome 3 0 Safari 4之后的版本中进行测试 IE8的实现方法与其他浏览不同 跨域请求 xff0c 顾名思义 xff0c 就是一个站点中的资源去访问另外一个不同域名站点上的
  • 分享30道Redis面试题,面试官能问到的我都找到了

    1 什么是Redis xff1f 简述它的优缺点 xff1f Redis本质上是一个Key Value类型的内存数据库 xff0c 很像memcached xff0c 整个数据库统统加载在内存当中进行操作 xff0c 定期通过异步操作把数据
  • AJAX(XMLHttpRequest)进行跨域请求方法详解(二)

    注意 xff1a 以下代码请在Firefox 3 5 Chrome 3 0 Safari 4之后的版本中进行测试 IE8的实现方法与其他浏览不同 2 xff0c 预检请求 预检请求首先需要向另外一个域名的资源发送一个 HTTP OPTION
  • 将文本文件的内容或者文字保存成图片

    调用方法 xff1a ConvertTextFileToImage Server MapPath 34 Log txt 34 Server MapPath 34 Log png 34 实现代码 xff1a void ConvertTextF
  • Windows 文件资源管理器中搜索带特殊字符文件名的方法

    今天处理一些文件 xff0c 文件夹这包含有类似 16年普通高等学校招生全国统一考试 英语 的文件名 xff0c 想全部找出来删除掉 xff0c 直接在文件资源管理器里面输入 是搜索不到想要的文件的 xff0c 这些是特殊字符 xff0c
  • 脑成像坐标系: MNI + Talairach

    一 脑成像坐标系 xff1a MNI Talairach MNI 脑 Montreal Neurological Institute 是基于大量的正常被试MRI扫描结果得到的标准脑 xff08 当然是欧罗巴人群的 xff09 Talaira
  • windows10隐藏分区(隐藏efi系统分区)

    我们需要使用diskpart来移除这个误显示的盘符 可能使用的命令 xff1a 1 以管理员身份运行CMD xff1b 2 运行diskpart命令 xff1b 3 list disk 显示所有安装的磁盘 xff1b 4 select di
  • 干支纪年和纪日算法

    怎样从已知年份和日期得到对应的干支纪年和纪日 文 xff0f 葛民勤 摘要 xff1a 从已知年份计算干支纪年很简单 xff1a 年份数减3 xff0c 除以10的余数是天干 xff0c 除以12的余数是地 支 从已知日期计算干支纪日的公式
  • Shell 脚本监控磁盘空间

    df 命令可以展示文件系统的磁盘有效空间信息 如果不指定文件名 xff0c 则当前所有挂载的文件系统有效空间信息 实现步骤 使用 df 查看磁盘信息使用 grep命令 过滤文件系统 xff0c 获取空间使用百分比通过Shell 脚本进行监控
  • R 实现熵权法计算权重

    按照信息论基本原理的解释 xff0c 信息是系统有序程度的一个度量 xff0c 熵是系统无序程度的一个度量 xff1b 根据信息熵的定义 xff0c 对于某项指标 xff0c 可以用熵值来判断某个指标的离散程度 xff0c 其信息熵值越小
  • R实现KMeans聚类算法教程

    本文和你一起学习无监督机器学习算法 kmeans算法 xff0c 并在R中给详细的实现示例和步骤 什么是k means聚类算法 聚类是从数据集中对观测值进行聚类的机器学习方法 它的目标是聚类相似观测值 xff0c 不同类别之间差异较大 聚类
  • 使用gopsutil获取OS信息

    生产环境通常需要掌握主机硬盘 CPU 内存 进程等资源使用情况 xff0c 可以执行系统命令获得 xff0c 通过os exec执行命令 xff0c 如 xff1a ps cd top xff0c 然后解析命令执行结果 对于linux操作系
  • gcc工具小结

    关于 l和 Wall选项的解析 xff1a Wall 打开gcc的所有警告 l参数就是用来指定程序要链接的库 xff0c l参数紧接着就是库名 xff0c 那么库名跟真正的库文件名有什么关系呢 xff1f 就拿数学库来说 xff0c 他的库
  • 如何在Java中调用Python

    Python语言有丰富的系统管理 数据处理 统计类软件包 xff0c 因此从java应用中调用Python代码的需求很常见 实用 DataX 是阿里开源的一个异构数据源离线同步工具 xff0c 致力于实现包括关系型数据库 MySQL Ora
  • ClickHouse 基于角色访问控制(RBAC)最佳实践

    本文介绍ClickHouse RBAC访问控制模型 包括如何启用SQL管理 xff0c 创建管理员用户 xff0c 创建角色 xff0c 授权 xff0c 细粒度列和行级授权 并通过示例进行验证实现过程 启用RBAC 在users xml中
  • R语言中mean函数

    mean函数是求算术平均值 用法 xff1a mean x trim 61 0 na rm 61 FALSE x是数值型 逻辑向量 trim表示截尾平均数 xff0c 0 0 5之间的数值 xff0c 如 xff1a 0 10表示丢弃最大1
  • 使用Spring @DependsOn控制bean加载顺序

    使用Spring 64 DependsOn控制bean加载顺序 spring容器载入bean顺序是不确定的 xff0c spring框架没有约定特定顺序逻辑规范 但spring保证如果A依赖B 如beanA中有 64 Autowired B

随机推荐

  • 使用R中merge()函数合并数据

    使用R中merge 函数合并数据 在R中可以使用merge 函数去合并数据框 xff0c 其强大之处在于在两个不同的数据框中标识共同的列或行 如何使用merge 获取数据集中交叉部分 merge 最简单的形式为获取两个不同数据框中交叉部分
  • 介绍java中Pair

    介绍java中Pair 在这篇文章中 xff0c 我们讨论了一个非常有用的编程概念 xff0c 配对 Pair 配对提供了一种方便方式来处理简单的键值关联 xff0c 当我们想从方法返回两个值时特别有用 在核心Java库中可以使用配对 Pa
  • python numpy 中linspace函数

    python numpy 中linspace函数 numpy提供linspace函数 有时也称为np linspace 是python中创建数值序列工具 与Numpy arange函数类似 xff0c 生成结构与Numpy 数组类似的均匀分
  • Spring框架学习重点概要笔记(一)

    spring框架的注解实现 xff1a xff08 1 xff09 首先在spring的核心配置文件中开启注解配置 xff1a xff08 2 xff09 64 Component 目前Spring中提供了四个注解 xff0c 相当于时Co
  • 做个爱读书的程序员

    很多时候我们抱怨工作过于忙碌 xff0c 疲于应付各种事情 但是往往即使有时间也总是会无所事事地浪费掉 xff0c 我们可以找很多理由去给自己解脱 xff0c 固然是想在忙碌之外给自己放松一下 xff0c 大多却是过于可惜的时候 今天跟一个
  • xming Error: Can‘t open display:

    运行 xclock xhost 报错 xff1a xming Error Can 39 t open display 需要安装xorg x11 xauth在运行 xclock 或 xhost root 64 stone yum y inst
  • onItemClickListener不起作用解决办法2(原创)

    写这边文章之前 xff0c 犹豫再三 xff0c 不知道会不会冒犯一位朋友 xff0c 他给我之前的一篇文章提出的意见 但我声明真心无意 xff0c 只是想把问题拿出来分析一下 xff0c 希望获得理解 listview在android开发
  • 关于STM32系列串口打印乱码原因解析

    STM32打印串口乱码 xff0c 如果你的配置确认没有问题 xff0c 那么最有可能是 HSE VALUE 这个值不对 xff0c 你可能使用的是一份demo程序 xff0c 而demo程序的时钟晶振和你的时钟晶振不一定都是一样 xff0
  • node.js提取html中的内部引入css和js代码,并修改为外部引入

    前提 xff1a 配置好node环境 xff0c 能够使用终端 xff08 cmd或Windows PowerShell xff09 node命令运行js文件 nodejs安装教程 某位大佬整理的nodejs入门教程 node xxx sp
  • Ffplay视频播放流程

    背景说明 FFmpeg是一个开源 xff0c 免费 xff0c 跨平台的视频和音频流方案 xff0c 它提供了一套完整的录制 转换以及流化音视频的解决方案 而ffplay是有ffmpeg官方提供的一个基于ffmpeg的简单播放器 学习ffp
  • 统计机器学习方法 for NLP:基于LSA的主题模型

    前言 最近在重刷李航老师的 统计机器学习方法 尝试将其与NLP结合 xff0c 通过具体的NLP应用场景 xff0c 强化对书中公式的理解 xff0c 最终形成 统计机器学习方法 for NLP 的系列 这篇将介绍潜在语义分析LSA xff
  • 知识图谱最新权威综述论文解读:时序知识图谱部分

    从最近一两年有关知识图谱的顶会论文中可以发现 xff0c 越来越多的国内外研究者开始关注动态时序知识图谱 xff0c 可见时序知识图谱已经成为了一大研究趋势 xff0c 相信之后会有更多相关研究出来 因此 xff0c 这期我们对综述论文的时
  • RabbitMQ简介、概念、安装、启动、工作模式

    RabbitMQ简介 概念 安装 启动 工作模式 1 RabbitMQ简介 RabbitMQ是支持多种消息协议 xff0c 易于部署和使用的开源消息代理服务器 xff0c 用于在分布式系统中存储转发消息 由以高性能 健壮以及可伸缩性出名的E
  • 递归删除某一文件夹下某一后缀名的所有文件,包括嵌套文件(例如删除.cfg文件)

    递归删除某一文件夹下某一后缀名的所有文件 xff0c 包括嵌套文件 xff08 例如删除 cfg文件 xff09 有时候我的电脑中会莫名生成很多 cfg文件 xff0c 一个一个的删除太繁琐了 xff0c 所有就写了这个函数 当然这个函数的
  • SQL 基础篇 SQL 4 查询结果限制返回行数

    SQL基础篇 汇总 刷题传送门 题目链接 题面 样例输入 drop table if exists user profile CREATE TABLE 96 user profile 96 96 id 96 int NOT NULL 96
  • RabbitMQ(一):工作模型

    RabbitMQ实现了AMQP协议 xff0c 所以RabbitMQ的工作模型也是基于AMQP的 Broker xff1a RabbitMQ宿主机 默认端口是5672 Connection xff1a 无论是生产者发送消息 xff0c 还是
  • 从零实现 USB转虚拟串口 CDC

    上一次调试是USB读卡器 43 FATFS xff0c 这次是USB转虚拟串口 说来也巧了 xff0c 这是我大学的毕设 xff0c 那个时候用STC芯片实现USB转串口 xff0c 差点儿没把我给搞死 多年后遇见故人 xff0c 甚是感慨
  • lwip之数据收发流程

    lwip从逻辑上看也是分为4层 xff1a 链路层 网络层 IP ARP xff08 ICMP IGMP这两个协议是网络层的补充协议 xff0c 并不严格属于网络层 xff09 传输层 TCP UDP 应用层 xff0c 基本等同TCP I
  • HIDL 原理及使用详解

    目录 1 HIDL 概念 1 1 Hidl 的简单介绍 1 2 Hidl 的设计目的 1 3 Hidl 与 Aidl 的对比 2 HIDL 类型 2 1 Passthrough 2 2 Binderized 3 HIDL 服务的实现 3 1
  • 实验报告 生产者――消费者问题算法的实现(cpp)

    问题的提出 xff1a 生产者 消费者 producer consumer 问题是一个著名的进程同步问题 它描述的是 有一群生产者进程在生产产品 xff0c 并将这些产品提供给消费者进程去消费 为使生产者进程与消费者进程能并发执行 xff0