操作系统实验报告 经典的生产者—消费者问题
操作系统实验三 生产者——消费者问题

操作系统实验三:生产者——消费者问题一、基本信息xxx 711103xx 2012年4月29日二、实验目的通过实验,掌握Windows和Linux环境下互斥锁和信号量的实现方法,加深对临界区问题和进程同步机制的理解,同时巩固利用Windows API和Pthread API进行多线程编程的方法。
三、实验内容1. 在Windows操作系统上,利用Win32 API提供的信号量机制,编写应用程序实现生产者——消费者问题。
2. 在Linux操作系统上,利用Pthread API提供的信号量机制,编写应用程序实现生产者——消费者问题。
3. 两种环境下,生产者和消费者均作为独立线程,并通过empty、full、mutex 三个信号量实现对缓冲进行插入与删除。
4. 通过打印缓冲区中的内容至屏幕,来验证应用程序的正确性。
四、实验步骤1. 创建3个信号量:Mutex、Full、Empty2. 主程序创建10个生产者线程和10个消费者线程,之后休眠一段时间3. 生产者线程中,休息一段2s后,生产一个0~10的随机数放入缓冲区里。
利用信号量Mutex产生对缓冲区使用的互斥功能,利用Empty和Full信号量来对缓冲区进行增加项4. 消费者线程中,休息4s时间后,消费一个缓冲区的数据。
利用信号量Mutex产生对缓冲区使用的互斥功能,利用Empty和Full信号量来对缓冲区进行增加项5. 主程序执行一段时间后,结束整个程序五、主要数据结构及其说明产品数量最大值const int MAX_SIZE = 10;缓冲区:int buffer[BUFFER_SIZE];int front; int rear; bool full;三个互斥信号量:HANDLE Mutex; HANDLE Full; HANDLE Empty;有关操作:用WaitForSingleSignal函数可以获得一个Mutex的所有权,类似于P 操作,而ReleaseMutex函数可以释放一个Mutex的所有权,类似于V 操作。
生产者消费者实验报告

生产者消费者实验报告生产者消费者实验报告引言:生产者消费者模型是计算机科学中的一个经典问题,用于解决多线程并发访问共享资源的同步问题。
在本实验中,我们通过编写一个简单的Java程序来模拟生产者消费者模型,并观察其运行结果和效果。
一、实验背景生产者消费者模型是一种常见的并发模型,用于解决多线程访问共享资源时可能出现的数据竞争和同步问题。
在该模型中,生产者负责生产数据并将其放入共享缓冲区,而消费者则负责从缓冲区中取出数据进行消费。
为了确保生产者和消费者之间的同步与互斥,需要使用合适的同步机制,如信号量、互斥锁等。
二、实验目的本实验的主要目的是通过编写一个简单的生产者消费者程序,验证该模型在多线程环境下的正确性和效果。
我们将通过观察程序的输出结果和运行时间来评估其性能,并分析其中可能存在的问题和改进空间。
三、实验设计1. 编写生产者类和消费者类:我们首先定义了一个共享缓冲区,用于存储生产者生产的数据。
然后,我们编写了一个生产者类和一个消费者类,分别实现了生产者和消费者的逻辑。
在生产者类中,我们使用了一个循环来模拟生产者不断地生产数据,并将其放入缓冲区。
而在消费者类中,我们同样使用了一个循环来模拟消费者不断地从缓冲区中取出数据进行消费。
2. 同步机制的选择:为了保证生产者和消费者之间的同步与互斥,我们选择了信号量作为同步机制。
在生产者类中,我们使用一个信号量来控制缓冲区的可用空间,当缓冲区已满时,生产者将等待,直到有可用空间。
而在消费者类中,我们同样使用一个信号量来控制缓冲区的可用数据,当缓冲区为空时,消费者将等待,直到有可用数据。
3. 实验参数的设置:为了模拟真实的生产者消费者场景,我们设置了以下参数:- 缓冲区大小:10- 生产者数量:3- 每个生产者生产的数据量:1000- 消费者数量:2四、实验结果与分析在运行实验程序后,我们观察到以下结果:1. 生产者和消费者之间的同步与互斥得到了有效保证,生产者在缓冲区已满时会等待,直到有可用空间;消费者在缓冲区为空时会等待,直到有可用数据。
“生产者消费者”实验

“生产者消费者”实验1.实验目的“生产者消费者”问题是一个著名的同时性编程问题的集合。
通过编写经典的“生产者消费者”问题的实验,读者可以进一步熟悉Linux 中多线程编程,并且掌握用信号量处理线程间的同步互斥问题。
2.实验内容“生产者消费者”问题描述如下。
有一个有限缓冲区和两个线程:生产者和消费者。
他们分别把产品放入缓冲区和从缓冲区中拿走产品。
当一个生产者在缓冲区满时必须等待,当一个消费者在缓冲区空时页必须等待。
它们之间的关系如下图所示:生产者1 2 3 …N 消费者图9.4 生产者消费者问题描述这里要求用有名管道来模拟有限缓冲区,用信号量来解决生产者消费者问题中的同步和互斥问题。
3.实验步骤(1)信号量的考虑这里使用3个信号量,其中两个信号量avail和full分别用于解决生产者和消费者线程之间的同步问题,mutex是用于这两个线程之间的互斥问题。
其中avail初始化为N(有界缓冲区的空单元数),mutex 初始化____________为1,full初始化为0。
(2)画出流程图本实验流程图如下图9.5 所示。
《嵌入式Linux应用程序开发详解》——第9章、多线程编程图9.5 “生产者消费者”实验流程图(3)编写代码本实验代码如下:/*product.c*/#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <pthread.h>#include <errno.h>#include <sys/ipc.h>#include <semaphore.h>#include <fcntl.h>#define FIFO "myfifo"#define N 5int lock_var;time_t end_time;char buf_r[100];sem_t mutex,full,avail;int fd;void pthread1(void *arg);void pthread2(void *arg);int main(int argc, char *argv[]){pthread_t id1,id2;pthread_t mon_th_id;int ret;end_time = time(NULL)+30;/*创建有名管道*/if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST)) printf("cannot create fifoserver\n");printf("Preparing for reading bytes...\n");memset(buf_r,0,sizeof(buf_r));/*打开管道*/fd=open(FIFO,O_RDWR|O_NONBLOCK,0);if(fd==-1){perror("open");exit(1);}《嵌入式Linux应用程序开发详解》——第9章、多线程编程/*初始化互斥信号量为1*/ret=sem_init(&mutex,0,1);/*初始化avail信号量为N*/ret=sem_init(&avail,0,N);/*初始化full信号量为0*/ret=sem_init(&full,0,0);if(ret!=0){perror("sem_init");}/*创建两个线程*/ret=pthread_create(&id1,NULL,(void *)productor, NULL); if(ret!=0)perror("pthread cread1");ret=pthread_create(&id2,NULL,(void *)consumer, NULL); if(ret!=0)perror("pthread cread2");pthread_join(id1,NULL);pthread_join(id2,NULL);}/*生产者线程*/void productor(void *arg){int i,nwrite;while(time(NULL) < end_time){/*P操作信号量avail和mutex*/sem_wait(&avail);sem_wait(&mutex);/*生产者写入数据*/if((nwrite=write(fd,"hello",5))==-1){if(errno==EAGAIN)printf("The FIFO has not been read yet.Please try later\n"); }elseprintf("write hello to the FIFO\n");/*V操作信号量full和mutex*/sem_post(&full);sem_post(&mutex);sleep(1);}}/*消费者线程*/void consumer(void *arg){int nolock=0;int ret,nread;while(time(NULL) < end_time){/*P操作信号量full和mutex*/sem_wait(&full);sem_wait(&mutex);memset(buf_r,0,sizeof(buf_r));if((nread=read(fd,buf_r,100))==-1){if(errno==EAGAIN)printf("no data yet\n");}printf("read %s from FIFO\n",buf_r);/*V操作信号量avail和mutex*/sem_post(&avail);sem_post(&mutex);}}4.实验结果运行该程序,得到如下结果:[root@(none) tmp]#./execPreparing for reading bytes...write hello to the FIFOread hello from FIFOwrite hello to the FIFOread hello from FIFOwrite hello to the FIFO《嵌入式Linux应用程序开发详解》——第9章、多线程编程read hello from FIFOwrite hello to the FIFOread hello from FIFO。
操作系统实验报告生产者消费者问题

操作系统课程设计一.实验目标完成N个生产者和M个消费者线程之间的并发控制,N、M不低于30,数据发送和接收缓冲区尺寸不小于20个(每个产品占据一个)。
其中生产者线程1、3、5、7、9生产的产品供所有奇数编号的消费者线程消费,只有所有奇数编号的消费者线程都消费后,该产品才能从缓冲区中撤销。
其中生产者线程2、4、6、8、10生产的产品所有偶数编号的消费者线程都可消费,任一偶数编号消费者线程消费该消息后,该产品都可从缓冲区中撤销。
其中11-20号生产者线程生产的产品仅供对应编号的消费者线程消费。
其他编号生产者线程生产的产品可由任意的消费者线程消费。
每个生产线程生产30个消息后结束运行。
如果一个消费者线程没有对应的生产者线程在运行后,也结束运行。
所有生产者都停止生产后,如果消费者线程已经没有可供消费的产品,则也退出运行。
二.实验原理2.1原理生产者与消费者线程采用posix互斥锁机制进行互斥进入各自的代码段,只有采用互斥锁临界区代码段才可以不被打扰的执行;同步机制采用的是posix条件变量pthread_cond_wait和pthraed_cond_signal进行同步的。
线程间的通信采用的是共享内存机制。
(注:所有的共享内存块是在进程里建立的,线程只需链接上各自的共享内存块即可,每一块共享内存的大小是100). 在这里共享内存设置成一个100的数组。
具体实施:(1)为1.3.5.7.9建立一个共享内存1号,1.3.5.7.9生产者线程生产的产品都放入这块共享内存缓冲区,所有奇数的消费者线程要消费的话,只需在消费者线程中链接上这块共享内存,就可以直接消费1.3.5.7.9生产者线程生产的产品。
(2)为2.4.6.8.10建立一块共享内存2号。
2.4.6.8.10生产的产品都放入2号共享内存缓冲区,所有的偶数的消费者线程只要链接上2号缓冲区,就可以消费2.4.6.8.10生产的产品。
当偶数消费者线程消费产品后,产品即可从缓冲区撤销,方法是在消费线程里将消费的产品在共享内存数组里置0。
操作系统实验报告生产者消费者问题

课程设计说明书山东科技大学2014年 1 月 1 日课程设计任务书一、课程设计题目:生产者消费者问题二、课程设计主要参考资料(1)《计算机操作系统》(修订版).汤子瀛.西安电子科技大学出版社。
(2)《数据结构》严蔚敏清华大学出版社(3)《操作系统概念》第六版三、课程设计应解决的主要问题:(1)了解信号量的使用(2)理解生产者消费者问题模型(3)掌握真确使用同步机制的方法(4)实现生产者消费者进程的互斥与同步四、课程设计相关附件(如:图纸、软件等):程序源代码五、任务发出日期: 2013-12-1 课程设计完成日期: 2014-12-25指导教师签字:系主任签字:指导教师对课程设计的评语成绩:指导教师签字:年月日生产者消费者问题一、设计目的1、了解信号量的使用2、加深对信号量机制的理解3、通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制.4、掌握基本的同步互斥算法,理解生产者与消费者模型5、了解多线程(多进程)的并发执行机制,线程(进程)间的同步与互斥二、设计要求1、理解生产者与消费者问题模型,掌握解决问题的算法思想2、掌握正确使用同步机制的方法3、每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者线程的标识符.4、生产者和消费者各有两个以上.5、多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码.三、设计说明(含系统框图和(或)主要算法的流程图)生产者流程图消费者流程图有n个生产者和m个消费者,连接在具有k个单位缓冲区的有界环转缓冲上,故又称有界缓冲问题。
其中Pi 和Cj都是并发进程,只要缓冲区未满,生产者进程Pi所生产的产品就可投入缓冲区;类似地,只要缓冲区非空,消费者进程Cj就可以从缓冲区取走并消耗产品。
生产者——消费者问题是典型的进程同步问题,这些进程必须按照一定的生产率和消费率来访问共享缓冲区,用P、V操作解决生产者和消费者共享单缓冲区的问题,可设置两个信号量empty和full,其初值分别为1和0,empty指示能否向缓冲区放入产品,full 指示能否从缓冲区取出产品。
生产者消费者问题实验报告

生产者消费者问题实验报告生产者消费者问题实验报告一、引言生产者消费者问题是计算机科学中一个经典的并发问题,主要涉及到多个线程之间的协作和资源的共享。
在本实验中,我们通过编写一个简单的程序来模拟生产者和消费者之间的交互过程,以深入理解该问题的本质和解决方案。
二、问题描述在生产者消费者问题中,有两类线程:生产者和消费者。
生产者线程负责生产一定数量的产品,而消费者线程则负责消费这些产品。
两类线程需要共享一个有限的缓冲区,生产者将产品放入缓冲区,而消费者从缓冲区中取出产品。
然而,缓冲区的容量是有限的,当缓冲区已满时,生产者需要等待,直到有空间可用。
同样地,当缓冲区为空时,消费者需要等待,直到有产品可用。
三、实验设计为了解决生产者消费者问题,我们采用了经典的解决方案——使用互斥锁和条件变量。
互斥锁用于保护共享资源的访问,保证同一时间只有一个线程可以访问共享资源。
而条件变量用于线程之间的通信,当某个条件不满足时,线程可以通过条件变量进入等待状态,直到条件满足时再被唤醒。
在我们的程序中,我们使用了一个有界缓冲区来模拟生产者消费者之间的交互。
缓冲区的大小可以通过参数进行设置。
我们创建了两个线程分别代表生产者和消费者,它们通过互斥锁和条件变量来实现同步。
生产者线程在缓冲区未满时将产品放入缓冲区,并通知消费者线程有产品可用;消费者线程在缓冲区非空时从缓冲区取出产品,并通知生产者线程有空间可用。
通过这种方式,我们保证了生产者和消费者之间的协作和资源的共享。
四、实验结果经过多次运行实验,我们观察到了以下现象:当生产者线程的生产速度大于消费者线程的消费速度时,缓冲区会被生产者填满,消费者需要等待;当消费者线程的消费速度大于生产者线程的生产速度时,缓冲区会被消费者清空,生产者需要等待。
只有当生产者和消费者的速度相等时,才能实现平衡的生产和消费。
此外,我们还发现在某些情况下,生产者和消费者线程可能出现死锁或饥饿现象。
死锁是指两个或多个线程相互等待对方释放资源,导致程序无法继续执行的情况。
生产消费系统实验报告(3篇)

第1篇一、实验目的1. 加深对进程概念的理解,明确进程和程序的区别。
2. 进一步认识并发执行的实质。
3. 验证用信号量机制实现进程互斥的方法。
4. 验证用信号量机制实现进程同步的方法。
二、实验环境1. 操作系统:Windows 102. 编程语言:C语言3. 开发工具:Visual Studio三、实验内容1. 生产者和消费者模型介绍生产者和消费者模型是操作系统中常见的一种并发控制模型,用于解决多个进程之间的同步和互斥问题。
在该模型中,生产者负责生成数据,消费者负责消费数据。
生产者和消费者通过共享资源(如缓冲区)进行通信。
2. 实验设计(1)环形缓冲区为了实现生产者和消费者的同步,我们设计了一个环形缓冲区,由若干个大小相等的缓冲块组成。
每个缓冲块可以容纳一个产品。
环形缓冲区的指针分别指向当前的第一个空缓冲块和第一个满缓冲块。
(2)信号量为了实现进程互斥和同步,我们使用了三个信号量:① 公用信号量:用于实现临界区互斥,初始值为1。
② 生产者私用信号量:用于实现生产者与消费者之间的同步,初始值为0。
③ 消费者私用信号量:用于实现生产者与消费者之间的同步,初始值为0。
(3)生产者进程生产者进程负责生成数据,并将数据存入环形缓冲区。
当环形缓冲区满时,生产者进程等待;当环形缓冲区有空位时,生产者进程继续生成数据。
(4)消费者进程消费者进程负责从环形缓冲区中取出数据并消费。
当环形缓冲区空时,消费者进程等待;当环形缓冲区有数据时,消费者进程继续消费数据。
3. 实验步骤(1)创建生产者进程和消费者进程。
(2)初始化信号量。
(3)运行生产者进程和消费者进程。
(4)按任意键停止程序,显示当前系统的各个参数的值。
四、实验结果与分析1. 实验结果通过运行实验程序,我们可以观察到生产者和消费者进程的运行情况。
当按下任意键停止程序时,程序将显示当前系统的各个参数的值,包括环形缓冲区的空位数量、生产者和消费者的状态等。
2. 分析(1)互斥:通过公用信号量实现生产者和消费者对环形缓冲区的互斥访问,防止了同时操作缓冲区的问题。
生产者与消费者实验报告

生产者和消费者实验报告【实验目的】1.加深对进程概念的理解,明确进程和程序的区别。
2.进一步认识并发执行的实质。
3.验证用信号量机制实现进程互斥的方法。
4.验证用信号量机制实现进程同步的方法。
【实验要求】用c语言编程搭建“生产者和消费者”经典进程通信问题的环境。
要求程序运行时,按任意键停止,显示当前系统的各个参数的值。
提交实验报告,以及相关程序列表。
打包成附件上传。
【实验环境】Visual C++6.0【实验内容】1.了解经典同步问题“生产者和消费者”生产者与消费者可以通过一个环形缓冲池联系起来,环形缓冲池由几个大小相等的缓冲块组成,每个缓冲块容纳一个产品。
每个生产者可不断地每次往缓冲池中送一个生产产品,而每个消费者则可不断地每次从缓冲池中取出一个产品。
指针i和指针j分别指出当前的第一个空缓冲块和第一个满缓冲块。
2.分析和理解(1)既存在合作同步问题,也存在临界区互斥问题合作同步:当缓冲池全满时,表示供过于求,生产者必须等待,同时唤醒消费者;当缓冲池全空时,表示供不应求,消费者应等待,同时唤醒生产者。
互斥:缓冲池显然是临界资源,所在生产者与消费都要使用它,而且都要改变它的状态。
(2)基于环形缓冲区的生产者与消费者关系形式描述:公用信号量mutex:初值为1,用于实现临界区互斥生产者私用信号量empty:初值为n,指示空缓冲块数目消费者私用信号量full:初值为0,指示满缓冲块数目整型量i和j初值为0,i指示首空缓冲块序号,j指示首满缓冲块序号(3)PV原语var mutex,empty,full:semaphore;i,j:integer;buffer:array[0...n-1] of item;i:=j:=1;Procedure producer;beginwhile true dobeginproduce a product;P(empty);P(mutex);buffer(i):=product;i:=(i+1) mod n;V(mutex);V(full);end;end;Procedure consumer;beginP(full);P(mutex);goods:=buffer(j);j:=(j+1) mod n;V(mutex);V(empty);consume a product;end;end;【实验源程序代码】#include <windows.h>#include <iostream>const unsigned short SIZE_OF_BUFFER = 10; //缓冲区长度unsigned short ProductID = 0; //产品号unsigned short ConsumeID = 0; //将被消耗的产品号unsigned short in = 0; //产品进缓冲区时的缓冲区下标unsigned short out = 0; //产品出缓冲区时的缓冲区下标int g_buffer[SIZE_OF_BUFFER]; //缓冲区是个循环队列bool g_continue = true; //控制程序结束HANDLE g_hMutex; //用于线程间的互斥HANDLE g_hFullSemaphore; //当缓冲区满时迫使生产者等待HANDLE g_hEmptySemaphore; //当缓冲区空时迫使消费者等待DWORD WINAPI Producer(LPVOID); //生产者线程DWORD WINAPI Consumer(LPVOID); //消费者线程int main(){//创建各个互斥信号g_hMutex = CreateMutex(NULL,FALSE,NULL);g_hFullSemaphore =CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);g_hEmptySemaphore =CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);//调整下面的数值,可以发现,当生产者个数多于消费者个数时,//生产速度快,生产者经常等待消费者;反之,消费者经常等待const unsigned short PRODUCERS_COUNT = 3; //生产者的个数const unsigned short CONSUMERS_COUNT = 1; //消费者的个数//总的线程数const unsigned short THREADS_COUNT =PRODUCERS_COUNT+CONSUMERS_COUNT;HANDLE hThreads[PRODUCERS_COUNT]; //各线程的handleDWORD producerID[CONSUMERS_COUNT]; //生产者线程的标识符DWORD consumerID[THREADS_COUNT]; //消费者线程的标识符//创建生产者线程for (int i=0;i<PRODUCERS_COUNT;++i){hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if (hThreads[i]==NULL) return -1;}//创建消费者线程for (i=0;i<CONSUMERS_COUNT;++i){hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&con sumerID[i]);if (hThreads[i]==NULL) return -1;}while(g_continue){if(getchar()){ //按回车后终止程序运行g_continue = false;}}return 0;}//生产一个产品。
操作系统之进程(生产者---消费者)实验报告

操作系统实验报告——生产者和消费者问题姓名:学号:班级:一、实验内容1、模拟操作系统中进程同步和互斥;2、实现生产者和消费者问题的算法实现;二、实验目的1、熟悉临界资源、信号量及PV操作的定义与物理意义;2、了解进程通信的方法;3、掌握进程互斥与进程同步的相关知识;4、掌握用信号量机制解决进程之间的同步与互斥问题;5、实现生产者-消费者问题,深刻理解进程同步问题;三、实验题目在Windows操作系统下用C语言实现经典同步问题:生产者—消费者,具体要求如下:(1)一个大小为10的缓冲区,初始状态为空。
(2)2个生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等待消费者取走数据之后再添加,重复10次。
页脚内容1(3)2个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等待生产者添加数据之后再读取,重复10次。
四、思想本实验的主要目的是模拟操作系统中进程同步和互斥。
在系统进程并发执行异步推进的过程中,由于资源共享和进程间合作而造成进程间相互制约。
进程间的相互制约有两种不同的方式。
(1)间接制约。
这是由于多个进程共享同一资源(如CPU、共享输入/输出设备)而引起的,即共享资源的多个进程因系统协调使用资源而相互制约。
(2)直接制约。
只是由于进程合作中各个进程为完成同一任务而造成的,即并发进程各自的执行结果互为对方的执行条件,从而限制各个进程的执行速度。
生产者和消费者是经典的进程同步问题,在这个问题中,生产者不断的向缓冲区中写入数据,而消费者则从缓冲区中读取数据。
生产者进程和消费者对缓冲区的操作是互斥,即当前只能有一个进程对这个缓冲区进行操作,生产者进入操作缓冲区之前,先要看缓冲区是否已满,如果缓冲区已满,则它必须等待消费者进程将数据取出才能写入数据,同样的,消费者进程从缓冲区读取数据之前,也要判断缓冲区是否为空,如果为空,则必须等待生产者进程写入数据才能读取数据。
在本实验中,进程之间要进行通信来操作同一缓冲区。
四川大学操作系统课程设计第三次实验报告生产者和消费者

实验报告(学生打印后提交)实验名称: 生产者和消费者问题实验时间: 2023年 5 月 5日●实验人员:●实验目的:掌握基本的同步互斥算法, 理解生产者和消费者模型。
●了解Windows 2023/XP中多线程的并发执行机制, 线程间的同步和互斥。
●学习使用Windows 2023/XP中基本的同步对象, 掌握相应的API●实验环境: WindowsXP + VC++6.0●运用Windows SDK提供的系统接口(API, 应用程序接口)完毕程序的功能。
API是操作系统提供的用来进行应用程序设计的系统功能接口。
使用API, 需要包含对API函数进行说明的SDK头文献, 最常见的就是windows.h实验环节:1.读懂源程序.2.编辑修改源程.......................................实验陈述:1.基础知识:本实验用到几个API函数:CreateThread CreateMutex, WaitForSingleObject, ReleaseMutexCreateSemaphore, WaitForSingleObject, ReleaseSemaphore, ReleaseMutex, nitializeCriticalSection, EnterCriticalSection, LeaveCriticalSection。
这些函数的作用:CreateThread, 功能:创建一个线程, 该线程在调用进程的地址空间中执行。
CreateMutex,功能:产生一个命名的或者匿名的互斥量对象。
WaitForSingleObject(相应p操作)锁上互斥锁, ReleaseMutex(相应v操作)打开互斥锁.。
CreateSemaphore, 创建一个命名的或者匿名的信号量对象。
信号量可以看作是在互斥量上的一个扩展。
WaitForSingleObject, 功能:使程序处在等待状态, 直到信号量(或互斥量)hHandle出现或者超过规定的等待最长时间, 信号量出现指信号量大于或等于1, 互斥量出现指打开互斥锁。
操作系统实验报告经典生产者—消费者问题范文大全[修改版]
![操作系统实验报告经典生产者—消费者问题范文大全[修改版]](https://img.taocdn.com/s3/m/81367c57d1f34693dbef3ed3.png)
第一篇:操作系统实验报告经典生产者—消费者问题实验二经典的生产者—消费者问题一、目的实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。
二、实验内容及要求编制生产者—消费者算法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。
1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。
生产者-消费者问题是典型的PV 操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。
缓冲池被占用时,任何进程都不能访问。
2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。
在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。
他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。
三、生产者和消费者原理分析在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。
四、生产者与消费者功能描述:生产者功能描述:在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
消费者功能描述:消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
五、实验环境操作系统环境:Windows 系统。
编程语言:C#。
生产者-消费者操作系统实验报告

一、目的和要求在采用多道程序设计的系统中,往往有若干个进程并发执行。
进程之间存在相互制约关系,本实验模拟在单处理器情况下的进程并发执行过程中,如何利用信号量机制实现并发进程的同步和互斥,帮助学生加深了解信号量机制、进程的同步和互斥。
二、实验内容利用高级语言模拟生产者-消费者算法算法。
分析:本算法需要解决以下问题1、生产者和消费者不能同时进入缓冲池2、缓冲池已满时,生产者不能再投放3、缓冲池为空时,消费者不能消费问题解决方法1、使用互斥变量mutex,为1时,可以进入,为0不可进入,通过lock()和unlock()实现锁定和解锁2、通过数组pbuffer[n]和pnum[n]实现生产者队列,分别记录生产者的商品以及生产者序号。
生产者进程产生时判断队列是否有进程等待,当缓冲区满时,进入队列,出现空区时,队列优先进入。
3、通过数组cnum[n]实现消费者队列,用于记录消费者编号,消费者进程产生时判断队列是否有进程等待,当缓冲区空时,进入队列,出现非空时,队列优先进入。
三、算法设计与实现主流程图示:生产者功能流程图示:消费者功能流程图示:实验函数void main();void run();void jiance(int mutex);//判断当前缓冲区是否被占用void lock(int mutex);//将缓冲池锁定mutex置为1void unlock(int mutex);//释放缓冲池mutex置为0void producer();//生产者进程int pro();//生产者随机生产的产品int pisempty();//判断生产者队列是否为空int bisempty();//判断缓冲池的各个缓冲区是否都已经被填满void input(int pn,int nextp);//在生产者队列为空的条件下,进行放入缓冲池的操作void input2();//生产者队列不为空时,排队进入缓冲池void inpb(int pn,int nextp);//生产者队列为空时进入生产者队列void customer();//消费者进程int cisempty();//判断消费者队列是否为空void outb(int cn);//消费者队列为空时,进入消费者队列void output2();//消费者队列不为空时,排队消费产品void output(int cn);//取出缓冲池商品,进行消费的操作四、运行界面。
操作系统实验报告-生产者与消费者

中南大学操作系统实验报告实验内容:Java多线程模拟生产者消费者问题实验时间:2014年5月指导老师:胡小龙老师姓名:代巍班级:信安1201班学号:**********一、实验目的对操作系统的整体进行一个模拟,通过实践加深对各个部分的管理功能的认识,还能进一步分析各个部分之间的联系,最后达到对完整系统的理解。
可以提高运用操作系统知识解决实际问题的能力;锻炼实际的编程能力,要达到以下要求。
(1)掌握进程(线程)的同步与互斥。
(2)掌握生产者消费者问题的实现方法。
(3)掌握多线程编程方法。
二、实验内容实现生产者消费者问题。
(1)假设循环缓冲队列共有多个缓冲单元。
(2)生产者线程的工作:生产出一个产品(即产生一个产品编号),按顺序往缓冲队列中“空”的缓冲单元放产品。
(3)消费者线程与的工作:从缓冲队列装有产品的缓冲单元中取出一个产品(即产品编号)。
(4)保证两个线程间的互斥和同步(5)在界面上打印缓冲队列的变化情况三、实验原理(1)生产者—消费者问题是一种同步问题的抽象描述。
(2)计算机系统中的每个进程都可以消费或生产某类资源。
当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
(3)而当某个进程释放资源时,则它就相当一个生产者。
模式还需要有一个缓冲区处于生产者和消费者之间,作为一个中介。
生产者把数据放入缓冲区,而消费者从缓冲区取出数据。
大概的结构如下图。
四、实验思想概述在操作系统中,线程有时被称为轻量级进程,是CPU使用的基本单位,它与属于同一进程的其他进程共享其他代码段、数据段和其他操作系统资源。
在Java中,线程的建立有两种方法:继承Thread类和实现Runnable接口。
其中,采用实现Runnable接口建立线程的好处是允许同时继承其他类从而实现多继承,并且在Java中,可采用synchronized或Object类的方法wait(),notify(),notifyAll()来实现多线程同步。
操作系统实验报告生产者消费者问题

《操作系统》实验报告2016年1月8日指导教师对实验报告的评语成绩:指导教师签字:年月日一、设计目标●完成N个生产者和M个消费者线程之间的并发控制,N、M不低于30,数据发送和接收缓冲区尺寸不小于20个(每个产品占据一个)。
●其中生产者线程1、3、5、7、9生产的产品供所有奇数编号的消费者线程消费,只有所有奇数编号的消费者线程都消费后,该产品才能从缓冲区中撤销。
●其中生产者线程2、4、6、8、10生产的产品所有偶数编号的消费者线程都可消费,任一偶数编号消费者线程消费该消息后,该产品都可从缓冲区中撤销。
●其中11-20号生产者线程生产的产品仅供对应编号的消费者线程消费。
●其他编号生产者线程生产的产品可由任意的消费者线程消费。
●每个生产线程生产30个消息后结束运行。
如果一个消费者线程没有对应的生产者线程在运行后,也结束运行。
所有生产者都停止生产后,如果消费者线程已经没有可供消费的产品,则也退出运行。
二、背景知识说明原理利用进程间共享的信号量、互斥锁等控制线程同步。
相关函数说明pthread_create():创建一个线程pthread_join():阻塞当前的线程,直到另外一个线程运行结束pthread_mutex_init():初始化互斥锁pthread_mutex_lock():占有互斥锁(阻塞操作)pthread_mutex_unlock():释放互斥锁sem_wait():获取信号量sem_post():释放信号量三、设计设计环境Linux操作系统(ubuntu12.04)gcc 4.6c语言Posix线程库编译命令:gcc consumer.c -lpthread -o consumer概要设计及详细设计图注释:(1)图:主函数流程(2)图:生产者流程(3)图:消费者流程(1)图(2) 图(3)图重要代码注释:#include<stdio.h>#include<malloc.h>#include<pthread.h>#include<semaphore.h>#define BUFFER_SIZE 30#define OVER (-1)struct Product{int tid;int data;};struct producers{//定义生产者条件变量结构struct Product buffer[BUFFER_SIZE];//缓冲区sem_t sem_read; // 读信号量sem_t sem_write; // 写信号量pthread_mutex_t wlock; // 缓冲区写锁pthread_mutex_t rlock; // 缓冲区读锁pthread_mutex_t lock; // thread_count的读写锁int readpos , writepos;//读写位置};struct producers buffer;int thread_count = 30; //存活生产者计数//用于在线程内部标识线程IDint ids[30] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}; int count = 0; // 计数消费产品数量int pcount = 0; // 计数生产产品数量void init(){//初始化相关锁和变量以及信号量buffer.readpos = 0;buffer.writepos = 0;//写信号量比缓冲区小1,防止缓冲区满和缓冲区空分不清sem_init(&buffer.sem_write, 0, BUFFER_SIZE-1);sem_init(&buffer.sem_read, 0, 0);pthread_mutex_init(&buffer.wlock, NULL);pthread_mutex_init(&buffer.rlock, NULL);pthread_mutex_init(&buffer.lock, NULL);}void put(int tid, int data){//缓冲区中放入一个数据sem_wait(&buffer.sem_write);//生产前先加锁,已防止其他线程同时生产pthread_mutex_lock(&buffer.wlock);buffer.buffer[buffer.writepos].tid = tid;buffer.buffer[buffer.writepos].data = data;buffer.writepos ++;++ pcount;if( buffer.writepos >= BUFFER_SIZE )buffer.writepos = 0;pthread_mutex_unlock(&buffer.wlock);sem_post(&buffer.sem_read);}//读数据并移走struct Product * get(int tid){struct Product * produce = NULL;//消费前先上锁,以防止其他线程同时消费pthread_mutex_lock(&buffer.rlock);// 如果生产者线程没有全部退出,或者缓冲区内仍有产品,则说明可以尝试去获取产品if(thread_count > 0 || buffer.readpos != buffer.writepos){//从信号量的值减去一个“1”,但它永远会先等待该信号量为一个非零值才开始做减法sem_wait( &buffer.sem_read );int pos = buffer.readpos;// 在已有产品中迭代,查找适合的产品while(pos != buffer.writepos){int id = buffer.buffer[pos].tid;if(id >10 && id <=20 && tid == id){ //如果产品是的生产者线程号10<id<=20 则可以供和它的线程号相同的消费者线程消费produce = (struct Product *)malloc(sizeof(struct Product));produce->tid = id;produce->data = buffer.buffer[pos].data;break;}else if(id <= 10 && (id%2 == tid%2)){ //如果产品是的生产者线程号<=10 则可以供和它的线程号奇偶性相同的消费者消费produce = (struct Product *)malloc(sizeof(struct Product));produce->tid = id;produce->data = buffer.buffer[pos].data;break;}else if(id > 20){ //如果产品是的生产者线程号>20则可以供任何消费者消费produce = (struct Product *)malloc(sizeof(struct Product));produce->tid = id;produce->data = buffer.buffer[pos].data;break;}pos = (pos+1)%BUFFER_SIZE;}if( produce ){ //如果取得了产品,消费计数+1,将在队头的元素覆盖到被取走的位置++ count;buffer.buffer[pos].tid = buffer.buffer[buffer.readpos].tid;buffer.buffer[pos].data = buffer.buffer[buffer.readpos].data;++ buffer.readpos;}if( buffer.readpos >= BUFFER_SIZE )buffer.readpos = 0;//如果取得了产品则释放一个缓冲区可写的信号量,否则释放一个可读的信号量if( produce )sem_post(&buffer.sem_write);elsesem_post(&buffer.sem_read);pthread_mutex_unlock(&buffer.rlock);}elsepthread_mutex_unlock(&buffer.rlock);return produce;}void *producer(void *data){ //每个线程循环生产30个产品int tid = *((int *)data);int n;for(n = 1; n <= 30; n++){printf("producer %d product %d \n", tid, n);put(tid, n);}// 每退出一个生产者线程后,thread_count 减1pthread_mutex_lock(&buffer.lock);-- thread_count;pthread_mutex_unlock(&buffer.lock);return NULL;}void *consumer(void * data){int tid = *((int *)data);struct Product *d = NULL;while(1){d = get(tid);if( d ) {printf("consumer %d consum %d from Producer %d \n", tid, d->data,d->tid);free(d);}pthread_mutex_lock(&buffer.lock);// 当所有生产者线程已退出,且缓冲区内已没有该线程可消费的产品时,退出该线程if(d == NULL && thread_count == 0 ){pthread_mutex_unlock(&buffer.lock);break;}elsepthread_mutex_unlock(&buffer.lock);}return NULL;}int main(void){pthread_t th_a[30], th_b[30];void *retval;init(&buffer);int i;for(i = 0; i<30; ++i){ // 创建生产者和消费者pthread_create(&th_a[i], NULL, producer, &ids[i]);pthread_create(&th_b[i], NULL, consumer, &ids[i]);}for(i = 0; i<30; ++i){ // 将线程加入到主线程组pthread_join(th_a[i], &retval);pthread_join(th_b[i], &retval);}printf("product %d products\n", pcount);printf("consume %d products\n", count);return 0;}四、测试测试数据文件格式测试数据由程序内部生成运行结果分析运行./consumer cat > output.txt 将输出结果保存在output.txt中待分析。
操作系统实验 生产者与消费者问题

实验一生产者和消费者问题1、程序流程图2、源代码#include <windows.h>#include <iostream>const unsigned short SIZE_OF_BUFFER = 10;unsigned short ProductID = 0;unsigned short ConsumeID = 0;unsigned short in = 0;unsigned short out = 0;int g_buffer[SIZE_OF_BUFFER];bool g_continue = true;HANDLE g_hMutex;HANDLE g_hFullSemaphore;HANDLE g_hEmptySemaphore;DWORD WINAPI Producer(LPVOID);DWORD WINAPI Consumer(LPVOID);int main(){ g_hMutex = CreateMutex(NULL,FALSE,NULL);g_hFullSemaphore = CreateSemaphore(NULL,SIZE_OF_BUFFER-1,SIZE_OF_BUFFER-1,NULL);g_hEmptySemaphore = CreateSemaphore(NULL,0,SIZE_OF_BUFFER-1,NULL);const unsigned short PRODUCERS_COUNT = 3;const unsigned short CONSUMERS_COUNT = 1;const unsigned short THREADS_COUNT = PRODUCERS_COUNT+CONSUMERS_COUNT;HANDLE hThreads[PRODUCERS_COUNT];DWORD producerID[CONSUMERS_COUNT];DWORD consumerID[THREADS_COUNT];for (int i=0;i<PRODUCERS_COUNT;++i){hThreads[i]=CreateThread(NULL,0,Producer,NULL,0,&producerID[i]);if (hThreads[i]==NULL) return -1;}for ( i=0;i<CONSUMERS_COUNT;++i){hThreads[PRODUCERS_COUNT+i]=CreateThread(NULL,0,Consumer,NULL,0,&consumerID[i]);if (hThreads[i]==NULL) return -1;}while(g_continue){if(getchar()){ //按回车后终止程序运行g_continue = false;}}return 0;}void Produce(){ std::cerr << "Producing " << ++ProductID << " ... ";std::cerr << "Succeed" << std::endl;}void Append(){ std::cerr << "Appending a product ... ";g_buffer[in] = ProductID;in = (in+1)%SIZE_OF_BUFFER;std::cerr << "Succeed" << std::endl;for (int i=0;i<SIZE_OF_BUFFER;++i){std::cout << i <<": " << g_buffer[i];if (i==in) std::cout << " <-- 生产";if (i==out) std::cout << " <-- 消费";std::cout << std::endl;}}void Take(){ std::cerr << "Taking a product ... ";ConsumeID = g_buffer[out];out = (out+1)%SIZE_OF_BUFFER;std::cerr << "Succeed" << std::endl;for (int i=0;i<SIZE_OF_BUFFER;++i){std::cout << i <<": " << g_buffer[i];if (i==in) std::cout << " <-- 生产";if (i==out) std::cout << " <-- 消费";std::cout << std::endl; }}void Consume(){ std::cerr << "Consuming " << ConsumeID << " ... ";std::cerr << "Succeed" << std::endl;}DWORD WINAPI Producer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hFullSemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Produce();Append();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hEmptySemaphore,1,NULL);}return 0;}DWORD WINAPI Consumer(LPVOID lpPara){ while(g_continue){WaitForSingleObject(g_hEmptySemaphore,INFINITE);WaitForSingleObject(g_hMutex,INFINITE);Take();Consume();Sleep(1500);ReleaseMutex(g_hMutex);ReleaseSemaphore(g_hFullSemaphore,1,NULL);}return 0;}3、实验结果3、实验心得通过做生产者消费者问题这个实验,让我更加明确了两者之间的联系和基本的同步互斥算法,了解多线程并发执行机制是怎样的,线程间的同步和互斥又是怎样的,还有缓冲区的在其中作用是什么。
生产者消费者问题实验报告

操作系统课程设计实验报告实验名称:生产者消费者问题姓名/学号:一、实验目的以生产者和消费者问题为例,学习Linux和Windows下进程通信、同步机制的具体实现方法,主要是信号量和共享内存。
熟悉相关系统API的用法。
二、实验内容使用共享内存和信号量机制来实现多个生产者/消费者进程间的通信和同步。
要求在Linux和Windows下分别实现。
缓冲区大小为3,初始为空。
2个生产者,随机等待一段时间,往缓冲区添加数据,重复6次。
3个消费者,重复4次。
三、实验环境Ubuntu 10.10 , GCC; Windows 7, VC 6.0;四、程序设计与实现1. Linux下:(1) 数据结构:a. 共享内存定义为一个结构,使得其数据成员更清晰且操作变得简单。
b. 共享缓冲区采用循环队列的数据结构,由上面的结构struct buf { int start; int end; int info[BUF_NUM]; }维护。
其中start为队头指针,end为队尾指针,info为数据区域。
(2) 算法:大致由三个模块组成:a.主程序(main):i.创建信号量、共享内存并进行初始化ii.创建生产者、消费者进程,生产者执行pro_fun(),消费者执行con_fun()iii.等待所有子进程的结束iv.删除信号量、共享内存b.生产者进程(pro_fun):i.通过key获得信号量、共享内存的ID,将内存添加到自己的地址空间ii.P(empty),P(mutex),Add(data),V(mutex),V(full)iii.解除和共享内存的关联c.消费者进程(con_fun):i.通过key获得信号量、共享内存的ID,将内存添加到自己的地址空间ii.P(full),P(mutex),Add(data),V(mutex),V(empty)iii.解除和共享内存的关联d.循环队列部分:加入数据:info[end] = value; end = (end + 1) % 3;取出数据:temp = info[start]; info[start] = 0; (start = start + 1)%3; return temp;(3) 程序流程图:a. 主函数:b. 生产者进程:c. 消费者进程和生产者类似4. Windows 下:(1) 数据结构:和Linux大致相同(2) 算法:a. 创建的子进程调用正在执行的文件本身,通过main函数的参数区分主进程和生产者、消费者进程。
操作系统实验报告-三大经典问题之生产者及消费者问题

计算机操作系统实验报告题目三大经典问题之生产者与消费者问题一、课程设计的性质与任务1、加深对并发协作进程同步与互斥概念的理解。
通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的容。
2、掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。
3、了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。
学习使用Windows2000/XP中基本的同步对象,掌握相应的API函数。
4、培养学生能够独立进行知识综合,独立开发较大程序的能力。
5、培养提高学生软件开发能力和软件的调试技术。
6、培养学生开发大型程序的方法和相互合作的精神。
7、培养学生的创新意识。
8、培养学生的算法设计和算法分析能力。
9、培养学生对问题进行文字论述和文字表达的能力。
二、课程设计的容及其要求在Windows XP、Windows2000等操作系统下,使用的VC、VB、Java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。
要求:(1)经调试后程序能够正常运行。
(2)采用多进程或多线程方式运行,体现了进程(线程)同步互斥的关系。
(3)程序界面美观。
三、实验原理本实验要求利用PV操作实现解决生产者——消费者问题中的同步问题。
此问题描述的是一群生产者进程在生产产品并将这些产品提供给消费者进程去消费,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区,消费者进程可从缓冲区中取走产品去消费,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满且尚未取出的缓冲区中投放产品,并且生产者消费者互斥使用缓冲区。
四、实验原理图五、算法实现(1)有一个生产者线程ProduceThread,有1个消费者进程CustomerThread;缓冲区为shareList。
生产者和消费者问题实验报告

格式: V。IDEnterCriticalSection( LPCRITICAL_SECTI。NIpCnticalSection ); LeaveCriticalSection的用法 功能:释放指定临界区对象的所有权。 格式: V。IDLeaveCriticalSection( LPCRITICAL.SECTI。NIpCriticalSection ); 2)程序结构 MI-I和序结构图 3)数据结构 (1)用一个整型数组Buffer-Critical来代表缓冲区。不管是生产产品还是对已有产品的消费都
Fer(inti-∙zi<R.reqvestHunU∙∙)
n_tħrei。.re<∣ι>tst[1]-((Thread!i⅞Fφ∙)(p))->thre⅛d.reqvest(1];
$10,P(LSl刊);
F∙r(l-∙U<R..req<∣p⅝tHuAU*∙)<
printfCXoo⅞uι⅞erVdrequesttoconς∣>aeVdpro^uct∖n-t∙-serlil.n_thr^a<l_requ«Mlt_for_sefuiphorPVanFarSinglp。bject(b_S^Mphor»(ii_thrp^d_reqiiest[i])v*-1);
文件G)⅛M∙Z)2«(X)收就")工具(D隅船。i) r^i∙-。CAftφct∙taisg4S∙S∖n<s∖Mmm6lr∙t0tA4面3f⅞文件夹∖*JfFl 文件和文件关任务 J创建一个新文件夹 θ将这个文件英宣布到 WHtb H共享,及伴英 IT*+6Y。rkSP∙c∙ Urn C*÷Ssιrc∙6KB Un VV忖Inttllistns 25KB 10簪巷
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
操作系统实验报告经典的生产者—消费者问题实验二经典的生产者—消费者问题一、目的实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。
二、实验内容及要求编制生产者—消费者算法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。
1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。
生产者-消费者问题是典型的PV操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。
缓冲池被占用时,任何进程都不能访问。
2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。
在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。
他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。
三、生产者和消费者原理分析在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
消费者线程从缓冲区中获得物品,然后释放缓冲区。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。
当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。
四、生产者与消费者功能描述:生产者功能描述:在同一个进程地址空间内执行两个线程。
生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。
当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。
消费者功能描述:消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。
五、实验环境操作系统环境:Windows系统。
编程语言:C#。
六、生产者与消费者的思路和设计1、程序流程图(1) 生产者(2) 消费者2、主要程序代码//初始化变量private void Form1_Load(object sender, EventArgs e){mutex = 1; //互斥信号量full = 0; //缓冲池中满缓冲区的数量empty = 5;//缓冲池中空缓冲区的数量count1 = 0;//生产的产品数目i = 0;lb_mutex.Text = "1";lb_full.Text = "0";lb_empty.Text = "5";}//消费者从缓冲区中消费一个产品private void consumer_Click(object sender, EventArgs e){if (full > 0){ //消费者已进入互斥临界区if (mutex == 1) //申请进入临界区{mutex = 0; //消费者已进入互斥临界区lb_mutex.Text = "0";timer_consumer.Enabled = true;//启动消费者消费缓冲区产品}else{MessageBox.Show("缓冲区被占用,请等待。
", "信息提"MessageBoxButtons.OK);}}else{MessageBox.Show("缓冲区为空,不能消费!", "信息提示", MessageBoxButtons.OK); }}//生产者向缓冲区中存入一个产品private void producer_Click(object sender, EventArgs e){count1 = count1 + 1; //生产一个产品if (empty > 0){ //有缓冲区可放产品if (mutex == 1){ //申请进入临界区mutex = 0; //生产者已进入临界区lb_mutex.Text = "0";timer1.Start(); //启动生产者将产品放入缓冲区}else{ //不能进入临界区count1 = count1 - 1;MessageBox.Show("缓冲区被占用,请等待。
", "信息提示", MessageBoxButtons.OK);}}else{MessageBox.Show("缓冲区已满!", "信息提示", MessageBoxButtons.OK); //无缓冲区可放产品count1 = count1 - 1;}}//生产者private void timer1_Tick_1(object sender, EventArgs e){if (bool1){switch (count1){case 1: pictureBox1.Visible = true; break;case 2: pictureBox2.Visible = true; break;case 3: pictureBox3.Visible = true; break;case 4: pictureBox4.Visible = true; break;case 5: pictureBox5.Visible = true; break;}lb_show.Text = "生产者进程占用缓冲区,请等待。
";bool1 = false;}else{switch (count1){case 1: pictureBox1.Visible = false; break;case 2: pictureBox2.Visible = false; break;case 3: pictureBox3.Visible = false; break;case 4: pictureBox4.Visible = false; break;case 5: pictureBox5.Visible = false; break;}lb_show.Text = "生产者进程占用缓冲区,请等待。
";bool1 = true;}i = i + 1;if (i == 5){ //循环缓冲区,首尾相接i = 0;timer1.Enabled = false;mutex = 1;lb_mutex.Text = "1";switch (count1){case 1: pictureBox1.Visible = true; break;case 2: pictureBox2.Visible = true; break;case 3: pictureBox3.Visible = true; break;case 4: pictureBox4.Visible = true; break;case 5: pictureBox5.Visible = true; break;}full = full + 1;lb_full.Text = full.ToString();empty = empty - 1;lb_empty.Text = empty.ToString();lb_show.Text = "生产结束!";}}//消费者private void timer_consumer_Tick(object sender, EventArgs e){if(bool1){switch(count1){case 1: pictureBox1.Visible = true; break;case 2: pictureBox2.Visible = true; break;case 3: pictureBox3.Visible = true; break;case 4: pictureBox4.Visible = true; break;case 5: pictureBox5.Visible = true; break;}lb_show.Text = "消费者进程占用缓冲区,请等待。
";bool1 =false;}else{switch(count1){case 1: pictureBox1.Visible = false; break;case 2: pictureBox2.Visible = false; break;case 3: pictureBox3.Visible = false; break;case 4: pictureBox4.Visible = false; break;case 5: pictureBox5.Visible = false; break;}lb_show.Text= "消费者进程占用缓冲区,请等待。
"; bool1= true;}i = i + 1;if(i==5){i = 0;timer_consumer.Enabled = false;mutex = 1;lb_mutex.Text= "1";switch(count1){case 1: pictureBox1.Visible = false; break;case 2: pictureBox2.Visible = false; break;case 3: pictureBox3.Visible = false; break;case 4: pictureBox4.Visible = false; break;case 5: pictureBox5.Visible = false; break;}count1 = count1 - 1;full = full - 1;lb_full.Text = full.ToString();empty = empty+1;lb_empty.Text=empty.ToString();lb_show.Text="消费结束!";}3、运行界面和运行结果一般情况下,点一次生产者按纽,mutex由1变为0,缓冲区呈现闪烁状态(表示正在存储),此时不可以再进行缓冲区操作,否则将显示“生产者进程正在占用缓冲区,请等待”。
闪烁约1.5秒后,mutex由0变为1,闪烁停止,表示存储过程结束;点一次消费者按纽,mutex由1变为0,缓冲区呈现闪烁状态(表示正在消费),此时不可以再进行缓冲区操作,否则将显示“消费者进程正在占用缓冲区,请等待”。