操原上机(二) 模拟实现“生产者-消费者”问题

2023-05-16

实验内容

在 windows 环境下,利用高级语言编程环境(限定为 VS 环境或 VC 环境) 调用 CreateThread 函数和相关的同步函数,模拟实现“生产者-消费者”问题。

实验过程

首先,先写个生成随机数的函数,代码如下:

int random(void){
	int a=time (NULL);
	srand(a);
	return rand()%1000;
}

然后,是生产者的功能函数,主要代码如下:

if(id == 1)	number = random()+1000;
		else number = random()+2000;
Buffer[rear]=number;
		printf("生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
rear = (rear+1)%N;
Sleep(600);

之后,需要加入pv操作以及临界区。这也是本题的难点所在。下面介绍windows环境是如何实现这些操作的。

临界区

Windows有专门的临界区对象。其应用也非常简单。如下:

CRITICAL_SECTION cs;	//声明临界区对象
InitializeCriticalSection(&cs);		//初始化临界区对象 
EnterCriticalSection(&cs);	//进入临界区
LeaveCriticalSection(&cs);	//离开临界区

信号量机制

Windows通过信号量机制来实现p操作和v操作。其应用函数如下:

HANDLE full =NULL;	//声明
full = CreateSemaphore(NULL ,0 ,N,"full");	//创建
CloseHandle(full); 	//关闭
HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full");	//打开
WaitForSingleObject(full,INFINITE); 	//p操作
ReleaseSemaphore(empty,1,NULL);	//v操作

在这些函数中
CreateSemaphore(NULL ,0 ,N,“full”)函数的第二个参数是信号量的初始值,应大于等于0;第三个参数为信号量的最大值,第四个参数为信号量的名称(可用于在其他地方打开该信号量)。
ReleaseSemaphore(empty,1,NULL)函数的第二个参数代表释放之后信号量的值加n。

了解了windows的临界区对象和信号量机制之后,我们就可以理解生产者功能函数加入这两者之后的代码了:

DWORD WINAPI Producer(LPVOID lpParam){
	int number;
	int id = ++i;
	HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full");
	HANDLE empty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"empty");
	while(1){
		if(id == 1)	number = random()+1000;
		else number = random()+2000;
		//p(empty)
		WaitForSingleObject(empty,INFINITE); 
		EnterCriticalSection(&cs);
		Buffer[rear]=number;
		printf("生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
		flag++;
		if(!flag){
			fp=fopen("C:\\Users\\HP\\Desktop\\记录.txt","w");
			if(fp==NULL){
				printf("can not load file!");
				exit(0); 
			}
		}
		fprintf(fp,"生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
	    rear = (rear+1)%N;
		LeaveCriticalSection(&cs);
		//v(full)
		ReleaseSemaphore(full,1,NULL);
		Sleep(600);
	}
}

以同样的方式,我们可以写出消费者的功能函数,然后再在主函数中用CreateThread调用这两个子程序,生成多线程。

完整代码:

#include <stdio.h>
#include <windows.h>
#include <time.h>
#define N 10

FILE *fp=NULL;
int flag = -1;
int Buffer[N];
int front=0,rear=0,i=0,j=0;
CRITICAL_SECTION cs;

int random(void){
	int a=time (NULL);
	srand(a);
	return rand()%1000;
}

//子线程函数  
DWORD WINAPI Producer(LPVOID lpParam){
	int number;
	int id = ++i;
	HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full");
	HANDLE empty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"empty");
	while(1){
		if(id == 1)	number = random()+1000;
		else number = random()+2000;
		//p(empty)
		WaitForSingleObject(empty,INFINITE); 
		EnterCriticalSection(&cs);
		Buffer[rear]=number;
		printf("生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
		flag++;
		if(!flag){
			fp=fopen("C:\\Users\\HP\\Desktop\\记录.txt","w");
			if(fp==NULL){
				printf("can not load file!");
				exit(0); 
			}
		}
		fprintf(fp,"生产者%d生产Buffer[%d],%d\n",id,rear,Buffer[rear]);
	    rear = (rear+1)%N;
		LeaveCriticalSection(&cs);
		//v(full)
		ReleaseSemaphore(full,1,NULL);
		Sleep(600);
	}
}

//子线程函数  
DWORD WINAPI Consumer(LPVOID lpParam){
	int id = ++j;
	HANDLE full =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"full");
	HANDLE empty =OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE,"empty");
	while(1){
		//p(full)
		WaitForSingleObject(full,INFINITE); 
		EnterCriticalSection(&cs);
    	printf("\t消费者%d消费Buffer[%d],%d\n",id,front,Buffer[front]);
    	flag++;
		if(!flag){
			fp=fopen("C:\\Users\\HP\\Desktop\\记录.txt","w");
			if(fp==NULL){
				printf("can not load file!");
				exit(0); 
			}
		}
		fprintf(fp,"\t消费者%d消费Buffer[%d],%d\n",id,front,Buffer[front]);
    	front = (front+1)%N;
		LeaveCriticalSection(&cs);
		//v(empty)
		ReleaseSemaphore(empty,1,NULL);
		Sleep(1000);
	}
}  
//主函数  
int main(){
	InitializeCriticalSection(&cs);		//初始化临界区对象 
	HANDLE full =NULL;
	full = CreateSemaphore(NULL ,0 ,N,"full");
	HANDLE empty =NULL;
	empty = CreateSemaphore(NULL ,N,N,"empty");
    HANDLE hThread[5];
    hThread[0] = CreateThread(NULL,0,Producer,NULL,0,NULL);
    hThread[1] = CreateThread(NULL,0,Producer,NULL,0,NULL);
    hThread[2] = CreateThread(NULL,0,Consumer,NULL,0,NULL);
    hThread[3] = CreateThread(NULL,0,Consumer,NULL,0,NULL);
    hThread[4] = CreateThread(NULL,0,Consumer,NULL,0,NULL);
	WaitForMultipleObjects(5,hThread,TRUE,10000); 	//等待子线程运行 
	fclose(fp);
	CloseHandle(full); 
	CloseHandle(empty); 
    return 0;  
}  

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

操原上机(二) 模拟实现“生产者-消费者”问题 的相关文章

随机推荐

  • vim如何批量注释

    1 ctrl 43 v 进入 2 按箭头 选中要注释的首行 3 按下大写 i 进入插入模式 4输入 按esc 就可以看到如下内容
  • vim中的替换

    Vim可以在尾行模式下使用 substitute命令将指定的字符串替换成其他目标字符串 通常我们可以使用该命令的缩写格式 s进行来进行vim字符串替换操作 一 Vim替换字符串命令的语法 Vim替换字符串命令的基本语法是 range s 目
  • docker删除无用的镜像等操作

    提供 prune命令 xff0c 用于移除不使用的镜像 容器 卷 网络 Prune images docker image prune移除没有标签并且没有被容器引用的镜像 xff0c 这种镜像称为 dangling 摇晃的 镜像 示例1 x
  • Python之requests模块-session

    http协议本身是无状态的 xff0c 为了让请求之间保持状态 xff0c 有了session和cookie机制 requests也提供了相应的方法去操纵它们 requests中的session对象能够让我们跨http请求保持某些参数 xf
  • git 对比两个分支差异

    1 显示出branch1和branch2中差异的部分 git diff branch1 branch2 stat 2 显示指定文件的详细差异 git diff branch1 branch2 具体文件路径 3 显示出所有有差异的文件的详细差
  • 操作系统中cpu如何工作

    扩充小知识 xff1a 这些硬件设备在一条总线上链接 xff0c 他们通过这条线进行数据交互 xff0c 里面的带头大哥就是CPU xff0c 拥有最高指挥权 那么它是如何工作的呢 xff1f A 取指单元 xff08 从内存中取得指令 x
  • dev/mapper的解释

    二 dev mapper目录的解释 为了方便叙述 xff0c 假设一台服务器有三块硬盘分别为a xff0c b xff0c c xff0c 每块硬盘的容量为1T 在安装Linux的时候 xff0c 先根据系统及自身的需要建立基本的分区 xf
  • Centos安装python39(其他版本也是一样的流程)

    Centos安装python39 其他版本也是一样的流程 centos安装python39 其他版本也是一样的流程 1 下载python39 可以去官网下载 xff0c 也可以去华为云下载 华为云 xff1a Index of python
  • centos 中如何启动两个rabbitmq 服务

    启动两个rabbitmq 服务 sudo RABBITMQ NODE PORT 61 5672 RABBITMQ DIST PORT 61 15672 RABBITMQ SERVER START ARGS 61 34 rabbitmq ma
  • 【码农本色】用数据解读我的2014

    转眼2014就过去了 xff0c 不禁感叹又老了一岁的同时 xff0c 却发现已经快研究生毕业了 xff0c 趁着这个活动简单总结下2014 1 实习篇 2014年一月份拿到了人生第一个实习offer xff0c 在sony这样的大公司做a
  • 出现Permission denied (publickey)的解决方法

    ssh root 64 10 240 1 161 报错 1 发现问题 在Linux终端使用ssh root 64 server ip来连接到远程服务器时 xff0c 出现Permission denied publickey 提示 2 分析
  • 23年4月开发语言最新排行榜公布

    随着时代的发展 xff0c 编程语言也在不断演化和发展 xff0c 每一种编程语言都有着其独特的特性和适用场景 在这篇博客中 xff0c 我们将来探讨一下各大编程语言的排行榜 xff0c 以及它们各自的优缺点和应用场景 下面是最新的 Tio
  • CommandNotFoundError: No command ‘conda activate‘

    前言 xff0c 在windows下使用coda 虚拟环境时 xff0c 在激活环境 conda activate env name 时 xff0c 报错找不到 conda activate 的命令 浪费了好久的时间 xff0c 找到了合适
  • Spring、SpringMVC常用注解总结

    一 Spring常用注解 64 Component xff1a 标注一个普通的Spring Bean类 64 Controller xff1a 标注一个控制器组件类 64 Service xff1a 标注一个业务层组件类 64 Reposi
  • 关于Ubuntu fix-broken 的使用

    执行命令 xff1a sudo apt fix broken install sudo apt get update sudo apt get upgrade 运行后可以解决由于依赖包缺失或错误引起的无法通过apt get来安装应用
  • java看书规划

    Java编程思想 大话设计模式 重构 改善既有代码的设计 effective java 深入理解Java虚拟机 Java并发编程实战 深入理解计算机系统 xff0c tcp ip详解 卷一 二 三 xff0c 数据结构与算法 xff08 三
  • 粗读Targeted Supervised Contrastive Learning for Long-Tailed Recognition

    相比于直接对图像进行分类 xff0c 本文更关注特征提取部分 xff0c 通过令提取的不同类特征在超球面上尽可能远离 xff0c 让属于同一类的特征尽可能靠近 xff0c 来提高模型面对样本不平衡时的分类性能 这是本文的方法和效果示意图 第
  • 运行 npm install 报错 command failed npm ERR! command C:\Windows\system32\cmd.exe /d /s /c node build.js

    运行 npm install 报错 command failed npm ERR command C Windows system32 cmd exe d s c node build js nodejs build js 具体看图片 xf
  • e2fsprogs : 预依赖: e2fslibs (= 1.42.13-1ubuntu1) 但是 1.42.13-1ubuntu1.1 正要被安装 E: 有未能满足的依赖关系

    问题 1 E 无法获得锁 var lib dpkg lock open 11 资源暂时不可用 E 无法锁定管理目录 var lib dpkg xff0c 是否有其他进程正占用它 xff1f 2 下列软件包有未满足的依赖关系 xff1a e2
  • 操原上机(二) 模拟实现“生产者-消费者”问题

    实验内容 在 windows 环境下 xff0c 利用高级语言编程环境 xff08 限定为 VS 环境或 VC 环境 xff09 调用 CreateThread 函数和相关的同步函数 xff0c 模拟实现 生产者 消费者 问题 实验过程 首