操作系统实验报告-三大经典问题之生产者与消费者问题
实验三 生产者-消费者问题

实验三生产者-消费者问题的实现实验类型验证性实验实验目的通过生产者-消费者问题的模拟,加深对进程同步、共享存储器通信的理解。
实验要求实现生产者消费者问题模拟,显示每次添加和读取数据时缓冲区的状态,生产者和消费者用进程模拟,缓冲区用共享内存来实现。
一个大小为3的缓冲区,初始为空;2个生产者:随机等待一段时间,往缓冲区添加数据,若缓冲区已满,等待消费者取走数据后再添加,重复6次。
3个消费者:随机等待一段时间,从缓冲区读取数据,若缓冲区为空,等待生产者添加数据后再读取,重复4次。
实验指导一、共享存储区通信1、共享存储区机制的概念共享存储区(Share Memory)是UNIX系统中通信速度最高的一种通信机制。
该机制可使若干进程共享主存中的某一个区域,且使该区域出现(映射)在多个进程的虚地址空间中。
另一方面,一个进程的虚地址空间中又可连接多个共享存储区,每个共享存储区都有自己的名字。
当进程间欲利用共享存储区进行通信时,必须先在主存中建立一共享存储区,然后将它附接到自己的虚地址空间上。
此后,进程对该区的访问操作,与对其虚地址空间的其它部分的操作完全相同。
进程之间便可通过对共享存储区中数据的读、写来进行直接通信。
应当指出,共享存储区机制只为进程提供了用于实现通信的共享存储区和对共享存储区进行操作的手段,然而并未提供对该区进行互斥访问及进程同步的措施。
因而当用户需要使用该机制时,必须自己设置同步和互斥措施才能保证实现正确的通信。
2、涉及的系统调用(1)shmget( )创建、获得一个共享存储区。
系统调用格式:shmid=shmget(key,size,flag)该函数使用头文件如下:#include<sys/types.h>#include<sys/ipc.h>#include<sys/shm.h>参数定义int shmget(key,size,flag);key_t key;int size,flag;其中:key是共享存储区的名字;(唯一标识共享内存的键值。
操作系统实验三 生产者——消费者问题

操作系统实验三:生产者——消费者问题一、基本信息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 操作。
生产者消费者问题实验报告

操作系统课程设计实验报告实验名称: 生产者消费者问题姓名/学号:一、实验目的以生产者和消费者问题为例, 学习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.大致由三个模块组成:i.主程序(main):ii.创建信号量、共享内存并进行初始化iii.创建生产者、消费者进程, 生产者执行pro_fun(), 消费者执行con_fun()iv.等待所有子进程的结束v.删除信号量、共享内存i.生产者进程(pro_fun):ii.通过key获得信号量、共享内存的ID, 将内存添加到自己的地址空间iii.P(empty), P(mutex), Add(data), V(mutex), V(full)iv.解除和共享内存的关联i.消费者进程(con_fun):ii.通过key获得信号量、共享内存的ID, 将内存添加到自己的地址空间iii.P(full), P(mutex), Add(data), V(mutex), V(empty)iv.解除和共享内存的关联循环队列部分:加入数据: 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函数的参数区分主进程和生产者、消费者进程。
计算机操作系统课程设计报告《生产者---消费者问题》

计算机操作系统课程设计报告《生产者---消费者问题》《计算机操作系统》课程设计题目:生产者---消费者问题专业:软件工程年级:2010级小组成员: A B指导教师:时间:地点:2012年5 月摘要生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例。
该问题描述了两个共享固定大小缓冲区的线程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。
生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。
与此同时,消费者也在缓冲区消耗这些数据。
该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
目录1. 概述 (4)2. 课程设计任务及要求 (4)2.1 设计任务 (4)2.2 设计要求 (4)2.3 分工日程表 (4)3. 算法及数据结构 (5)3.1算法的总体思想 (5)3.2 生产者模块 (5)3.3 消费者模块 (7)4. 程序设计与实现 (8)4.1 程序流程图 (8)4.2 程序代码 (9)4.3 实验结果 (14)5. 结论 (17)6. 收获、体会和建议 (17)6.1收获......................................... 错误!未定义书签。
7. 参考文献 (18)1. 概述本课题设计是完成了“操作系统原理”课程进行的一次全面的综合训练,通过这次课程设计,充分检验学生对课程的掌握程度和熟练情况,让学生更好的掌握操作系统的原理及其实现方法,加深对课程的基础理论和算法的理解,加强学生的动手能力。
生产者消费者问题实验报告

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

实验3 经典同步互斥问题1.实验目的·通过编写程序熟悉并发,同步/互斥,死锁等概念2.实验内容[基本要求]编写Linux环境下C程序,实现3个经典的同步/互斥问题[具体要求]·生产者/消费者问题设计思路:1)首先建立缓冲池,循环队列#define BUFFSIZE 9 // 缓冲池大小struct queue_type //缓冲池队列{int buff[BUFFSIZE];int front; //队头,消费者从对头取出"产品”int rear; //队尾,生产者从队尾放入"产品“}Q={{0},0,0};2)设置信号量实现互斥sem_t pro_empty; // 生产者私有信号量,表示空缓冲区数目。
sem_t con_full; //消费者私有变量,表示有产品的缓冲区数目。
sem_t mutex; //实现对临界区互斥访问的信号量3)设计生产者函数生产者必须首先申请空缓冲区,缓冲区有空闲才能生产sem_wait(&pro_empty);然后进入缓冲区生产,进入之前利用mutex互斥sem_wait(&mutex); //信号量申请缓冲区互斥Q.buff[Q.rear] = 1; //将产品放入rear所指向的缓冲区print();Q.rear = (Q.rear+1) % BUFFSIZE;//注意要模,因为是循环队列sem_post(&mutex); //释放互斥sem_post(&con_full);//释放满缓冲区4)设计消费者函数消费者必须首先申请满缓冲区,缓冲区有东西才能消费sem_wait(&con_full);然后进入缓冲区消费,进入之前利用mutex互斥sem_wait(&mutex);Q.buff[Q.front] = 0; //从front所指向的缓冲区取产品print();Q.front = (Q.front+1) % BUFFSIZE;sem_post(&mutex);//释放队列互斥sem_post(&pro_empty);// //释放空缓冲区·读者问题设计思路:1)设置互斥锁pthread_mutex_t writer_lock = PTHREAD_MUTEX_INITIALIZER;//同一时间只能一个人写文件,互斥pthread_mutex_t access_readercount = PTHREAD_MUTEX_INITIALIZER;//同一时间只能有一个人访问readerCnt2)设计写者函数进入临界区写,进入之前利用互斥锁互斥pthread_mutex_lock(&writer_lock);write();pthread_mutex_unlock(&writer_lock);3)设计读者优先函数如果有一个读者在读,则后面的读者来到都可以读,所以要把所有写者锁上pthread_mutex_lock(&access_readercount);//临界区互斥readercount++;if(readercount == 1){pthread_mutex_lock(&writer_lock);//把读者锁上}pthread_mutex_unlock(&access_readercount);读数据,读之前利用互斥锁互斥pthread_mutex_unlock(&access_readercount);read();pthread_mutex_lock(&access_readercount);如果最后一个读者退出,则要把原来锁上写者的锁打开pthread_mutex_lock(&access_readercount);readercount--;if(readercount == 0){pthread_mutex_unlock(&writer_lock);}pthread_mutex_unlock(&access_readercount);·写者问题设计思路:1)设置互斥锁//实现读者读时互斥pthread_mutex_t access_readercount = PTHREAD_MUTEX_INITIALIZER;//实现写者写时互斥pthread_mutex_t access_writercount = PTHREAD_MUTEX_INITIALIZER;//实现把写者锁上pthread_mutex_t writer_lock = PTHREAD_MUTEX_INITIALIZER;//实现把一个读者锁上pthread_mutex_t reader_lock = PTHREAD_MUTEX_INITIALIZER;//实现把成千上万读者锁上pthread_mutex_t outer_lock = PTHREAD_MUTEX_INITIALIZER;2)设计写者优先函数如果第一个写者来了,那么禁止所有读者pthread_mutex_lock(&access_writercount);{//临界区,希望修改writercount,独占writercountwritercount++;//写者数量加1if(writercount == 1){//后续的读者加入待读队列pthread_mutex_lock(&reader_lock);}}pthread_mutex_unlock(&access_writercount);写数据,写之前互斥pthread_mutex_lock(&writer_lock);{//临界区,限制只有一个写者修改数据write();}pthread_mutex_unlock(&writer_lock);最后一个写者走了,则释放之前所有被禁止的读者pthread_mutex_lock(&access_writercount);{//临界区,希望修改writercount,独占writercountwritercount--;//写者数量减1if(writercount == 0){//释放待读序列中的读者pthread_mutex_unlock(&reader_lock);}}pthread_mutex_unlock(&access_writercount);3)·哲学家问题只有当哲学家的左右两只筷子均可以用的时候,才允许其拿起筷子进餐,否则该哲学家一直请求左边的筷子,若为非阻塞状态(左边的筷子信号量为1则直接占有,信号量为0则进入阻塞状态),则拿起,然后测试右手筷子是什么状态,右边的筷子若信号量为0,则阻塞,进入等待,非阻塞,则吃设计思路:1)设置左右手筷子int right = (id + 1) % PHILO_NUM;int left = id;2)思考状态,然后此哲学家先处于睡眠,然后状态变为饥饿case THINKING:usleep(300);state = HUNGRY;strcpy(ptrState,"thinking");break;3)饥饿状态,则去拿筷子case HUNGRY:if(sem_wait(&chopsticks[left]) == 0){//左筷子非阻塞状态if(sem_trywait(&chopsticks[right]) == 0){//测试右筷子,若为非阻塞,则拿起strcpy(ptrState,"eating ");state = EATING;//状态变为吃}else{state = THINKING;//拿不到筷子,变为思考状态sem_post(&chopsticks[left]);//释放已经请求的得到的左筷子}}break;4)吃状态,释放左右手筷子,之后状态变为思考sem_post(&chopsticks[left]);sem_post(&chopsticks[right]);usleep(500);state = THINKING;strcpy(ptrState,"thinking");break;·代码有注释,提交实验报告和源代码[进一步要求]·多个生产者和消费者在主函数中可以输入你想设置的生产者和消费者数目printf("please input the producers number: ");scanf("%d",&M);printf("please input the consumers number: ");scanf("%d",&N);·多个读者和写者,考虑读者优先或是写者优先宏定义读者写者数目#define N_WRITER 3 //写者数目#define N_READER 5 //读者数目·用区别于示例代码的思想实现哲学家问题利用了sem_trywait()函数·可视化展示输出结果。
生产者与消费者实验报告

生产者和消费者实验报告【实验目的】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、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
计算机操作系统实验报告题目三大经典问题之生产者与消费者问题
一、课程设计的性质与任务
1、加深对并发协作进程同步与互斥概念的理解。
通过编写程序实现进程同步和互斥,使学生掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的内容。
2、掌握进程和线程的概念,进程(线程)的控制原语或系统调用的使用。
3、了解Windows2000/XP中多线程的并发执行机制,线程间的同步和互斥。
学习使用Windows2000/XP中基本的同步对象,掌握相应的
API函数。
4、培养学生能够独立进行知识综合,独立开发较大程序的能力。
5、培养提高学生软件开发能力和软件的调试技术。
6、培养学生开发大型程序的方法和相互合作的精神。
7、培养学生的创新意识。
8、培养学生的算法设计和算法分析能力。
9、培养学生对问题进行文字论述和文字表达的能力。
二、课程设计的内容及其要求
在Windows XP、Windows 2000等操作系统下,使用的VC、VB、Java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。
要求:(1)经调试后程序能够正常运行。
(2)采用多进程或多线程方式运行,体现了进程(线程)同步互斥的关系。
(3)程序界面美观。
三、实验原理
本实验要求利用PV操作实现解决生产者——消费者问题中的同步问题。
此问题描述的是一群生产者进程在生产产品并将这些产品提供给消费者进程去消费,在两者之间设置了一个具有n个缓冲区的缓冲池,生产者进程将它所生产的产品放入一个缓冲区,消费者进程可从缓冲区中取走产品去消费,但它们之间必须保持同步,即不允许消费者进程到一个空缓冲区去取产品,也不允许生产者进程向一个已装满且尚未取出的缓冲区中投放产品,并且生产者消费者互斥使用缓冲区。
四、实验原理图
五、算法实现
(1)有一个生产者线程ProduceThread,有1个消费者进程CustomerThread;缓冲区为shareList。
(2)使用线程同步:用synchonized关键字(加锁)使得一个时间
内只能有一个线程得到执行,另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块;wait()让线程进入等待状态;notify()函数唤醒一个处于等待状态的线程。
(3)程序运行流程图如下:(如不在外部中断,程序将一直循环运行)
六、源代码
package操作系统;
/*
*产品类
*/
publicclass Goods {
int id;
String name;
public String toString(){
return id+" "+name;
}
}
package操作系统;
import java.util.List;
/*
* 消费者线程:有产品时可以取出,无产品时等待 */
publicclass CustomerThread extends Thread{ private ListshareList;
CustomerThread(ListshareList){
this.shareList=shareList;
}
publicvoid run(){
System.out.println("消费线程已启
动..."+shareList.size());
while(true){
try{
synchronized(shareList){
while(shareList.size()==0){
//如果没有产品,消费线程则等待
shareList.wait();
}
while(shareList.size()>0){
System.out.println("<---消费线程取出产品:"+shareList.remove(0).toString());
shareList.notify();
}
}
}catch(Exception ef){
ef.printStackTrace();
}
}
}
}
package操作系统;
import java.util.List;
/*
* 生产者线程:无数据时再存,存入一个要发通知 */
publicclass ProduceThread extends Thread{ //构造器参数是生产线程要放入的队列
public ProduceThread(ListshareList){
this.shareList=shareList;
}
publicvoid run(){
System.out.println("生产线程已启动..."+shareList.size());
while(true){
try{
Thread.sleep(2000);
synchronized(shareList){
while(shareList.size()>0){
shareList.wait();
}
while(shareList.size()==0){
Goods gs = new Goods();
count++;
gs.id=count;
="产品"+count;
System.out.println("--->生产线程放入对象:"+gs.toString());
shareList.add(gs);
//通知消费线程,队列中有对象了
shareList.notify();
}
}
}catch(Exception ef){
ef.printStackTrace();
}
}
}
//用来标记放入对象的每一个独立ID号
privatestaticint count=0;
//与消费者线程或以共同存取的对象列表
private ListshareList;
}
package 操作系统;
importjava.util.LinkedList;
importjava.util.List;
public class Manage {
//主函数
public static void main(String[] args){
//生产\消费线程交换对象的队列
List shareList = new java.util.LinkedList();
//启动生产线程
newProduceThread(shareList).start();
//启动消费线程
newCustomerThread(shareList).start();
}
}
七、运行结果
八、实验心得
在此次实验中我们模拟PV 操作同步机构,来解决消费者与生产者这两个进程之间的同步协调问题。
实验中值得注意的是解决进程同步需要做哪些工作,如何利用信号量机制来解决进程同步问题等等。
通过本次实验,我对操作系统的p、v有了进一步认识,深入
了解了p、v操作的实质和其重要性,加深了我对操作系统中多线程机制的理解和认识,更让我认识到知识的掌握,仅靠学习理论知识是远远不够的,要与实际动手操作相结合才能更好地理解和分析问题。
此外,我也发现自己在编程上仍存在较大的问题,本次实验让我对java语言的线程编写水平有了提高。
我日后会不断加深各方面知识的学习,弥补自己的不足。
实验给了我们实践的机会,给了我们理论结合实际的机会,从实验中可以学到很多东西,不仅仅是书本上的东西这么简单,更是培养了我们动手能力和自学能力,还有更重要的是对待事情严谨的态度,我定会以更加严谨认真的态度对待每次实验。