生产者消费者问题实现

合集下载

C++实现生产者和消费者

C++实现生产者和消费者

C++实现⽣产者和消费者传统的⽣产者消费者模型⽣产者-消费者模式是⼀个⼗分经典的多线程并发协作的模式,弄懂⽣产者-消费者问题能够让我们对并发编程的理解加深。

所谓⽣产者-消费者问题,实际上主要是包含了两类线程,⼀种是⽣产者线程⽤于⽣产数据,另⼀种是消费者线程⽤于消费数据,为了解耦⽣产者和消费者的关系,通常会采⽤共享的数据区域,就像是⼀个仓库,⽣产者⽣产数据之后直接放置在共享数据区中,并不需要关⼼消费者的⾏为;⽽消费者只需要从共享数据区中去获取数据,就不再需要关⼼⽣产者的⾏为。

但是,这个共享数据区域中应该具备这样的线程间并发协作的功能:本⽂的⽣产者消费者模型但是本篇⽂章不是说的多线程问题,⽽是为了完成⼀个功能,设置⼀个⼤⼩固定的⼯⼚,⽣产者不断的往仓库⾥⾯⽣产数据,消费者从仓库⾥⾯消费数据,功能类似于⼀个队列,每⼀次⽣产者⽣产数据放到队尾,消费者从头部不断消费数据,如此循环处理相关业务。

代码下⾯是⼀个泛型的⼯⼚类,可以不断的⽣产数据,消费者不断的消费数据。

//// Created by muxuan on 2019/6/18.//#include <iostream>#include <vector>using namespace std;#ifndef LNRT_FACTORY_H#define LNRT_FACTORY_Htemplate<typename T>class Factory {private:vector<T> _factory;int _size = 5;bool logEnable = false;public:void produce(T item);T consume();void clear();void configure(int cap, bool log = false);};template<typename T>void Factory<T>::configure(int cap, bool log) {this->_size = cap;this->logEnable = log;}template<typename T>void Factory<T>::produce(T item) {if (this->_factory.size() < this->_size) {this->_factory.push_back(item);if (logEnable) cout << "produce product " << item << endl;return;}if (logEnable) cout << "consume product " << this->consume() << endl;this->_factory[this->_size - 1] = item;if (logEnable) cout << "produce product " << item << endl;}template<typename T>T Factory<T>::consume() {T item = this->_factory[0];for (int i = 1; i < this->_size; i++) this->_factory[i - 1] = this->_factory[i];return item;}template<typename T>void Factory<T>::clear() {for (int i = 0; i < this->_size; i++) if (logEnable) cout << "consume product " << this->consume() << endl;}#endif //LNRT_FACTORY_H测试Factory<int> factory;factory.configure(5,true);for (int i = 0; i < 10; ++i) {factory.produce(i);}factory.clear();⽤途该类可以很⽅便的实现分组问题,⽐如处理视频序列时候将第i帧到第j帧数据作为⼀个分组处理任务,可以⽤下⾯的⽅法来实现。

操作系统中的经典问题——生产者消费者问题(两种方式实现)

操作系统中的经典问题——生产者消费者问题(两种方式实现)

操作系统中的经典问题——⽣产者消费者问题(两种⽅式实现)操作系统中的经典问题——⽣产者消费者问题(两种⽅式实现)1、问题引⼊:什么是⽣产者消费者问题?⽣产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是⼀个多线程同步问题的经典案例。

该问题描述了共享固定⼤⼩缓冲区的两个线程——即所谓的“⽣产者”和“消费者”——在实际运⾏时会发⽣的问题。

⽣产者的主要作⽤是⽣成⼀定量的数据放到缓冲区中,然后重复此过程。

与此同时,消费者也在缓冲区消耗这些数据。

该问题的关键就是要保证⽣产者不会在缓冲区满时加⼊数据,消费者也不会在缓冲区中空时消耗数据。

.要解决该问题,就必须让⽣产者在缓冲区满时休眠(要么⼲脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,⽣产者才能被唤醒,开始往缓冲区添加数据。

同样,也可以让消费者在缓冲区空时进⼊休眠,等到⽣产者往缓冲区添加数据之后,再唤醒消费者。

通常采⽤进程间通信的⽅法解决该问题。

如果解决⽅法不够完善,则容易出现死锁的情况。

出现死锁时,两个线程都会陷⼊休眠,等待对⽅唤醒⾃⼰。

该问题也能被推⼴到多个⽣产者和消费者的情形。

2、问题分析该问题需要注意的⼏点:1. 在缓冲区为空时,消费者不能再进⾏消费2. 在缓冲区为满时,⽣产者不能再进⾏⽣产3. 在⼀个线程进⾏⽣产或消费时,其余线程不能再进⾏⽣产或消费等操作,即保持线程间的同步4. 注意条件变量与互斥锁的顺序由于前两点原因,因此需要保持线程间的同步,即⼀个线程消费(或⽣产)完,其他线程才能进⾏竞争CPU,获得消费(或⽣产)的机会。

对于这⼀点,可以使⽤条件变量进⾏线程间的同步:⽣产者线程在product之前,需要wait直⾄获取⾃⼰所需的信号量之后,才会进⾏product的操作;同样,对于消费者线程,在consume之前需要wait直到没有线程在访问共享区(缓冲区),再进⾏consume的操作,之后再解锁并唤醒其他可⽤阻塞线程。

信号量实现生产者消费者问题

信号量实现生产者消费者问题

生产者——消费者问题一、实验目的通过实验,掌握Windows和Linux环境下互斥锁和信号量的实现方法,加深对临界区问题和进程同步机制的理解,同时巩固利用Windows API和Pthread API进行多线程编程的方法。

二、实验内容1. 在Windows操作系统上,利用Win32 API提供的信号量机制,编写应用程序实现生产者——消费者问题。

2. 在Linux操作系统上,利用Pthread API提供的信号量机制,编写应用程序实现生产者——消费者问题。

3. 两种环境下,生产者和消费者均作为独立线程,并通过empty、full、mutex三个信号量实现对缓冲进行插入与删除。

4. 通过打印缓冲区中的内容至屏幕,来验证应用程序的正确性。

三、实验步骤㈠设计思路①声明三个信号量,互斥信号量mutex,计数信号量empty初始化值100,技术信号量full初始化值0,并声明一个缓冲区char类型的buffer数组,大小为10,初始值为N。

②produce利用信号量形成对buffer临界生产,添加一个元素进去,赋值为A。

consume利用信号量形成对buffer临界消费,从buffer 中拿出来一个元素,并将buffer中原来元素赋为B。

每访问一次临界区,就输出buffer值。

③创建多线程,其中5个生产者,和5个消费者,每个线程最多操作缓冲区10次。

㈡流程图四、主要数据结构及其说明声明一个char类型的数组buffer,大小为10,用来做生产者和消费者共同访问的共享变量,可视做临界区。

五、程序运行时的初值和运行结果Win32下Linux下六、实验体会本实验总体感觉不是很难,就是将用信号量解决生产者消费者问题用具体的代码实现。

主要的工作就是分别在Win32和Pthread下用不同的函数名来实现P操作和V操作。

还有就是如何验证程序的正确性,就是通过没执行一次操作就输出缓冲区buffer值来判断是否符合要求。

七、源程序并附上注释Win32下#include <IOSTREAM.h>#include <STDIO.H>#include <windows.h>HANDLE Empty,full,mutex;//声明3个信号量,互斥信号量mutex,计数信号量full和Emptyint x=0;int y=0;char *buffer;//缓冲区buffer//输出buffervoid output(){for (int i=0;i<10;i++){cout<<buffer[i]<<" ";}cout<<"\n";}DWORD WINAPI produce(LPVOID param){int j=0;do{WaitForSingleObject(Empty,INFINITE);//buffer空余量减一WaitForSingleObject(mutex,INFINITE);//形成互斥,只能一个线程去生产cout<<GetCurrentThreadId()<<"^^^^^"<<j<<"^^^^^";//输出当前线程的id号,和执行的次数buffer[(y++%10)]='A';//生产赋值为Aoutput();//输出bufferj++;ReleaseSemaphore(mutex,1, NULL);//取消互斥,允许其他线程生产ReleaseSemaphore(full,1, NULL);//可以消费量加1 } while (j!=10);//每个线程生产10次return 0;}DWORD WINAPI consume(LPVOID param){int j=0;do{WaitForSingleObject(full,INFINITE);//将可以消费量减1WaitForSingleObject(mutex,INFINITE);//形成互斥访问,自能一个线程可以访问。

生产者消费者问题实验报告

生产者消费者问题实验报告

操作系统课程设计实验报告实验名称: 生产者消费者问题姓名/学号:一、实验目的以生产者和消费者问题为例, 学习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函数的参数区分主进程和生产者、消费者进程。

操作系统之生产者消费者问题(c++实现)

操作系统之生产者消费者问题(c++实现)
void info()//程序提示信息
{
std::cout<<"* - - - - - - - - - - - - - - - - - - - - - - - *"<<std::endl;
std::cout<<"|课程设计课题:生产者-消费者问题的模拟实现|"<<std::endl;
std::cout<<"|指导老师:李先锋|"<<std::endl;
bool g_continue = 1;//控制程序运行:1表示继续运行?0表示停止运行
HANDLE g_hMutex;//线程间的互斥信号量
HANDLE g_hFullSemaphore;//资源信号量:缓冲区满
HANDLE g_hEmptySemaphore;//资源信号量:缓冲区空
DWORD WINAPI Producer(LPVOID);//生产者线程
std::cout<<"|学生:丁可|"<<std::endl;
std::cout<<"|班级: B计123班|"<<std::endl;
std::cout<<"* - - - - - - - - - - - - - - - - - - - - - - - *"<<std::endl;
std::cout<<" ==》按回车开始该程序"<<std::endl;
getchar();
}
/*----------------------------程序提示信息结束------------------------------*/

操作系统_生产者与消费者问题的实现

操作系统_生产者与消费者问题的实现
shm_unlink("/shm"); /*删除共享内存区,程序中基本上保证了子进程先退出,因此父进程中无wait操作且这部操作放在父进程这里*/
//shmctl(shmid,IPC_RMID,&buf);
//del_sem(semid);
return 0;
}
/*生产者写5次后退出*/
void producer(key_t keyFull, key_t keyEmpty)
empty Write P1 : 2
empty Write P2 : 4
in = 0
Write : 5
full Write V1 : 0
full Write V2 : 0
full Read P2 : 0
out = 0
Read : 5
empty Read V1 : 4
empty Read V2 : 5
Write : 7
full Write V1 : 0
full Write V2 : 0
full Read P2 : 0
out = 2
Read : 7
empty Read V1 : 4
empty Read V2 : 5
Read Finish
p(empty); /*是否有空缓冲区,有则占有,无则被挂起,是原子操作*/
printf("empty Write P2 : %d\n", semctl(empty, 0, GETVAL, 0));
value_write++;
in = in++;
pData[in] = value_write;
in = in % 5;
printf("full Write V2 : %d\n", semctl(full, 0, GETVAL, 0));

实习5生产者-消费者问题实现

实习5生产者-消费者问题实现
模拟操作系统中进程同步和互斥。
一、实习内容
熟悉临界资源、信号量及PV操作的定义与物理意义了解进程通信的方法掌握进程互斥与进程同步的相关知识掌握用信号量机制解决进程之间的同步与互斥问题实现生产者-消费者问题,深刻理解进程同步问题
二、实习目的
在Linux操作系统下用C实现经典同步问题:生产者—消费者,具体要求如下: (1)一个大小为10的缓冲区,初始状态为空。 (2)2个生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等待消费者取走数据之后再添加,重复10次。 (3)2个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等待生产者添加数据之后再读取,重复10次。
管道通信系统 向管道提供输入的发送进程,以字符流方式将大量的数据送入管道,而接收进程从管道中接收数据。由于发送进程和接收进程是利用管道进行通信的,故称为管道通信。 为了协调发送和接收双方的通信,管道通信机制必须提供以下3方面的协调功能。 (1)互斥 当一个进程正在对pipe文件进行读或写操作时,另一个进程必须等待。 (2)同步 当写进程把一定数量的数据写入pipe文件后,便阻塞等待,直到读进程取走数据后,再把写进程唤醒。 (3)确认对方是否存在 只有确定对方已存在时,才能进行管道通信,否则会造成因对方不存在而无限制地等待。
在这个问题当中,我们采用信号量机制进行进程之间的通信,设置两个信号量,空的信号量和满的信号量。 在Linux系统中,一个或多个信号量构成一个信号量集合。使用信号量机制可以实现进程之间的同步和互斥,允许并发进程一次对一组信号量进行相同或不同的操作。每个P、V操作不限于减1或加1,而是可以加减任何整数。在进程终止时,系统可根据需要自动消除所有被进程操作过的信号量的影响 1.缓冲区采用循环队列表示,利用头、尾指针来存放、读取数据,以及判断队列是否为空。缓冲区中数组大小为10; 2.利用随机函数rand()得到A~Z的一个随机字符,作为生产者每次生产的数据,存放到缓冲区中;

生产者消费者问题实验报告

生产者消费者问题实验报告

生产者消费者问题实验报告生产者消费者问题实验报告一、引言生产者消费者问题是计算机科学中一个经典的并发问题,主要涉及到多个线程之间的协作和资源的共享。

在本实验中,我们通过编写一个简单的程序来模拟生产者和消费者之间的交互过程,以深入理解该问题的本质和解决方案。

二、问题描述在生产者消费者问题中,有两类线程:生产者和消费者。

生产者线程负责生产一定数量的产品,而消费者线程则负责消费这些产品。

两类线程需要共享一个有限的缓冲区,生产者将产品放入缓冲区,而消费者从缓冲区中取出产品。

然而,缓冲区的容量是有限的,当缓冲区已满时,生产者需要等待,直到有空间可用。

同样地,当缓冲区为空时,消费者需要等待,直到有产品可用。

三、实验设计为了解决生产者消费者问题,我们采用了经典的解决方案——使用互斥锁和条件变量。

互斥锁用于保护共享资源的访问,保证同一时间只有一个线程可以访问共享资源。

而条件变量用于线程之间的通信,当某个条件不满足时,线程可以通过条件变量进入等待状态,直到条件满足时再被唤醒。

在我们的程序中,我们使用了一个有界缓冲区来模拟生产者消费者之间的交互。

缓冲区的大小可以通过参数进行设置。

我们创建了两个线程分别代表生产者和消费者,它们通过互斥锁和条件变量来实现同步。

生产者线程在缓冲区未满时将产品放入缓冲区,并通知消费者线程有产品可用;消费者线程在缓冲区非空时从缓冲区取出产品,并通知生产者线程有空间可用。

通过这种方式,我们保证了生产者和消费者之间的协作和资源的共享。

四、实验结果经过多次运行实验,我们观察到了以下现象:当生产者线程的生产速度大于消费者线程的消费速度时,缓冲区会被生产者填满,消费者需要等待;当消费者线程的消费速度大于生产者线程的生产速度时,缓冲区会被消费者清空,生产者需要等待。

只有当生产者和消费者的速度相等时,才能实现平衡的生产和消费。

此外,我们还发现在某些情况下,生产者和消费者线程可能出现死锁或饥饿现象。

死锁是指两个或多个线程相互等待对方释放资源,导致程序无法继续执行的情况。

生产者消费者问题(C++实现)

生产者消费者问题(C++实现)

⽣产者消费者问题(C++实现)#include <windows.h>#include <iostream>#include<cstdio>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(){int i;///创建各个互斥信号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 (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;}///⽣产⼀个产品。

生产者与消费者的问题-----操作系统课程设计

生产者与消费者的问题-----操作系统课程设计

闽江学院计算机系网络操作系统课程设计设计内容:进程机制与并发程序设计——linux下生产者与消费者的问题实现目录:一、设计内容 (3)二、设计思想 (4)三、系统结构 (5)四、PV操作代码 (5)五、C++程序代码 (6)六、运行结果截图 (9)七、参考文献 (11)八、实验总结 (11)一、设计内容进程机制与并发程序设计————linux下生产者与消费者的问题实现1.实验目的(1)掌握基本的同步互斥算法,理解生产者和消费者同步的问题模型。

(2)了解linux中多线程的并发执行机制,线程间的同步和互斥。

2、实验环境:C/C++语言编译器3、实验要求(1)创建生产者和消费者线程在linux环境下,创建一个控制台进程,在此进程中创建n个线程来模拟生产者或者消费者。

这些线程的信息由本程序定义的“测试用例文件”中予以指定。

该文件的格式和含义如下:31 P 32 P 43 C4 14 P 25 C 3 1 2 4第一行说明程序中设置几个临界区,其余每行分别描述了一个生产者或者消费者线程的信息。

每一行的各字段间用Tab键隔开。

不管是消费者还是生产者,都有一个对应的线程号,即每一行开始字段那个整数。

第二个字段用字母P或者C区分是生产者还是消费者。

第三个字段表示在进入相应线程后,在进行生产和消费动作前的休眠时间,以秒计时;这样做的目的是可以通过调整这一列参数,控制开始进行生产和消费动作的时间。

如果是代表生产者,则该行只有三个字段。

如果代表消费者,则该行后边还有若干字段,代表要求消费的产品所对应的生产者的线程号。

所以务必确认这些对应的线程号存在并且该线程代表一个生产者。

(2)生产和消费的规则在按照上述要求创建线程进行相应的读写操作时,还需要符合以下要求:①共享缓冲区存在空闲空间时,生产者即可使用共享缓冲区。

②从上边的测试数据文件例子可以看出,某一生产者生产一个产品后,可能不止一个消费者,或者一个消费者多次地请求消费该产品。

生产者消费者问题实现

生产者消费者问题实现
线程间的同步方法大体可分为两类:用户模式和内核模式。内核模式就是指
利用系统内核对象的单一性来进行同步, 使用时需要切换内核态与用户态,而用 户模式就是不需要切换到内核态,只在用户态完成操作。
用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。内 核模式下的方法有:事件,信号量,互斥量。
在本实验中,线程之间要进行通信来操作同一缓冲区。一般来说,线程间的 通信可以划分为三种:1)使用全局变量实现线程间通信;2)使用消息实现线程 间通信;3)使用CEvent类实现线程间通信 。
待生产者添加数据之后再读取,重复10次。
(4)按要求输出。
实验步骤:
首先,使用一个互斥锁,意味着资源槽机制就不能使用了。因为资源槽虽以 用一个互斥锁完成,但是需要有额外的通信,如果使用管道通信,则管道也必须 是互斥,这就不满足1个互斥锁的要求。其次,要求生产者一直生产,这就否定 了另外一种方法:消费者、生产者的位置均平等,消费者消费的时候生产者不能 生产,生产者生产的时候消费者不能消费。因此,就需要采用A要求,也就是循
环链表的形式。
为了保证互斥要求,需要定义一个数据结构,这个数据结构包含两个指针, 一个读一个写,同时有一个资源数目量,告诉生产者和消费者是否可以生产或者 消费。由于该数据结构很小,因而可以对此结构互斥访问。同时,对于每组数据, 都有一个标志位,表示此组数据是否被占用,生产者和消费者均可以先占用此位 置然后完成相应的操作。
四、实验内容及步骤
实验内容:模拟操作系统中进程同步和互斥。
实现经典同步问题:生产者一消费者,具体要求如下(可采用C++或者java)
(1)一个大小为10的缓冲区,初始状态为空。
⑵2个等 待消费者取走数据之后再添加,重复10次。

操作系统实验报告经典生产者—消费者问题范文大全[修改版]

操作系统实验报告经典生产者—消费者问题范文大全[修改版]

第一篇:操作系统实验报告经典生产者—消费者问题实验二经典的生产者—消费者问题一、目的实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。

二、实验内容及要求编制生产者—消费者算法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。

1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。

生产者-消费者问题是典型的PV 操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。

缓冲池被占用时,任何进程都不能访问。

2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。

在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。

他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。

三、生产者和消费者原理分析在同一个进程地址空间内执行两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

消费者线程从缓冲区中获得物品,然后释放缓冲区。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放一个空缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻挡,直到新的物品被生产出来。

四、生产者与消费者功能描述:生产者功能描述:在同一个进程地址空间内执行两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

消费者功能描述:消费者线程从缓冲区获得物品,然后释放缓冲区,当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

五、实验环境操作系统环境:Windows 系统。

编程语言:C#。

基于消息队列实现生产者—消费者问题的设计思路_概述说明

基于消息队列实现生产者—消费者问题的设计思路_概述说明

基于消息队列实现生产者—消费者问题的设计思路概述说明1. 引言1.1 概述生产者-消费者问题是计算机科学中经典的并发控制问题,它涉及到多个生产者和消费者同时访问共享资源的情况。

在实际应用中,生产者通常负责生成数据或任务,并将其存入一个缓冲区,而消费者则负责从缓冲区中取出数据或任务进行处理。

由于生产者和消费者之间可能存在速率差异,因此需要一种有效的机制来调节两者之间的同步和协作关系。

本文将介绍基于消息队列实现生产者-消费者问题的设计思路。

通过利用消息队列这一轻量级的通信机制,可以实现高效、可靠的生产者-消费者模型,并解决其可能面临的并发控制和缓冲区管理等挑战。

1.2 文章结构本文共分为五个部分,具体内容包括引言、生产者-消费者问题概述、消息队列的基本原理与特点、实现生产者-消费者问题的设计思路介绍以及结论与展望。

每个部分将逐步展开对相关内容进行详细阐述。

1.3 目的本文旨在提供一种基于消息队列的解决方案来实现生产者-消费者问题,并通过对相关概念、原理和特点的介绍,帮助读者深入理解该问题以及设计思路。

同时,本文还将展望该设计思路的应用前景,探讨其在实际项目中的可行性和优势,为读者提供参考和借鉴。

2. 生产者—消费者问题概述2.1 问题背景生产者-消费者问题是计算机科学中的一个经典同步问题,描述了多个线程之间共享有限资源的情况。

在这个问题中,存在两种角色:生产者和消费者。

生产者负责生成数据并将其放入缓冲区,而消费者则从缓冲区中取出数据并进行处理。

生产者-消费者问题在实际应用中非常常见,例如多线程编程、进程间通信等场景都会涉及到该问题。

解决这个问题需要考虑如何合理地调度生产者和消费者的行为,以保证数据的正确性和有效性。

2.2 涉及的关键概念解释在理解生产者-消费者问题之前,我们需要对一些关键概念进行解释。

- 缓冲区(Buffer):用于存储待处理数据的空间。

它可以是一个队列、堆栈或其他类型的数据结构。

- 同步(Synchronization):指协调不同线程之间的执行顺序或操作访问共享资源时的互斥操作。

生产者消费者问题模拟实现(z)PDF

生产者消费者问题模拟实现(z)PDF

生产者-消费者实验1.1实验目的和要求1.1.1实验目的操作系统的基本控制和管理控制都围绕着进程展开,其中的复杂性是由于支持并发和并发机制而引起的。

自从操作系统中引入并发程序设计后,程序的执行不再是顺序的,一个程序未执行完而另一个程序便已开始执行,程序外部的顺序特性消失,程序与计算不再一一对应。

并发进程可能是无关的,也可能是交互的。

然而,交互的进程共享某些变量,一个进程的执行可能会影响其他进程的执行结果,交互的并发进程之间具有制约关系、同步关系。

其中典型模型便是生产者-消费者模型。

本实验通过编写和调试生产者-消费者模拟程序,进一步认识进程并发执行的实质,加深对进程竞争关系,协作关系的理解,掌握使用信号量机制与P、V操作来实现进程的同步与互斥。

1.1.2实验要求1.用高级语言编写一个程序,模拟多个生产者进程和多个消费者进程并发执行,并采用信号量机制与P、V操作实现进程间同步与互斥。

2.撰写实验报告,报告应包含以下内容:(1)实验目的;(2)实验内容;(3)设计思路;(4)程序流程图;(5)程序中主要数据结构和函数说明;(6)带注释的源程序代码;(7)程序运行结果及分析;(8)实验收获与体会。

1.2预备知识1.2.1生产者—消费者问题生产者—消费者问题表述如下:如图 3.1所示,有n个生产者和m个消费者,连接在具有k个单位缓冲区的有界环状缓冲上,故又称有界缓冲问题。

生产者不断生成产品,只要缓冲区未满,生产者进程pi所生产的产品就可投入缓冲区;类似的,只要缓冲区非空,消费者进程cj就可以从缓冲区取走并消耗产品。

图 3.1 生产者—消费者问题示意图著名的生产者—消费者问题(producer-consumer problem)是计算机操作系统中并发进程内在关系的一种抽象,是典型的进程同步问题。

在操作系统中,生产者进程可以是计算进程、发送进程,而消费者进程可以是打印进程、接收进程等,解决好生产者—消费者问题就解决了一类并发进程的同步问题。

操作系统实现生产者消费者问题

操作系统实现生产者消费者问题

操作系统综合设计实现生产者消费者问题目录第一部分:实现生产者与消费者问题一、题目 (2)1、课程设计目的 (2)2、课程设计要求 (2)二、设计内容 (2)三、开发环境 (3)四、分析设计 (3)1、设计原理 (3)2、涉及的数据结构 (5)3、流程图 (6)五、运行示例及结果分析 (8)1、运行示例 (8)2、运行结果分析: (9)六、个人体会 (9)七、附录(源程序) (10)第一部分:实现生产者与消费者问题一、题目:实现生产者与消费者问题此问题是经典的进程同步互斥问题,问题描述参见教材第36页和第46页,要求编程实现,生产者放入产品的和消费者取走产品的速度可以调节。

1、课程设计目的:在我们所学的《操作系统》这门课程中,关于经典进程的同步问题进行了一定的描述和探讨,介绍了几个经典的算法,需要我们在实践中学会熟练运用。

在生产者与消费者问题中,需要我们了解进程同步的概念,理解信号量机制的原理,掌握运用信号量解决进程同步问题的方法,进而学会运用进程的同步与互斥解决生产者与消费者的冲突问题。

2、课程设计要求:生产者与消费者问题可以算作是经典进程同步问题的典型代表。

该课程设计要求运用基于单缓冲区和多缓冲区的生产者与消费者问题的多种实现机制,其中利用了数据结构中的循环队列和堆栈来模拟实现是一种比较容易实现的方法。

这种思想能够帮助我们更好的理解所学内容,并加以锻炼我们的动手实践能力,实现它内在具有的超强的参考价值和实践意义。

该课程设计通过了解进程间的两种制约关系,从而理解信号量机制;通过对实例的分析和讨论,理解信号量机制实现进程的同步及互斥的方法;通过对经典进程同步问题的剖析,初步掌握运用信号量解决进程同步问题的方法。

二、设计内容在同一个进程地址空间内执行的两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

消费者线程从缓冲区中获得物品,然后释放缓冲区。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

生产者消费者问题实现

生产者消费者问题实现

生产者消费者问题实现班级姓名学号一.实验目的1.熟悉临界资源、信号量及PV操作的定义与物理意义2.了解线程通信的方法3.掌握线程互斥与同步的相关知识4.掌握用信号量机制解决线程之间的同步与互斥问题5.实现生产者-消费者问题,深刻理解线程同步问题二、实验的硬件、软件平台硬件:计算机软件:操作系统win10应用软件:Dev C++三、实验原理生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。

在同一个线程地址空间内执行的两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

消费者线程从缓冲区中获得物品,然后释放缓冲区。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

多个生产/消费者在有界缓冲上操作。

它利用N个字节的共享内存作为有界循环缓冲区,利用写一字符模拟放一个产品,利用读一字符模拟消费一个产品。

当缓冲区空时消费者应阻塞睡眠,而当缓冲区满时生产者应当阻塞睡眠。

一旦缓冲区中有空单元,生产者线程就向空单元中入写字符,并报告写的内容和位置。

一旦缓冲区中有未读过的字符,消费者线程就从该单元中读出字符,并报告读取位置。

生产者不能向同一单元中连续写两次以上相同的字符,消费者也不能从同一单元中连续读两次以上相同的字符。

在进行多线程编程时,由于资源共享和进程间合作而造成进程间相互制约,难免还要碰到两个问题,那就线程间的互斥与同步:线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。

当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。

操作系统课程设计-管程的实现(生产者消费者问题)

操作系统课程设计-管程的实现(生产者消费者问题)

操作系统课程设计2、管程的实现(生产者消费者问题)1.设计背景:管程是一种高级抽象数据类型,它支持在它的函数中隐含互斥操作。

结合条件变量和其他一些低级通信原语,管程可以解决许多仅用低级原语不能解决的同步问题。

例如,本实验中利用管程提供一个不会发生死锁的生产者消费者问题就是利用管程的很好的例子。

管程封装了并发进程或线程要互斥执行的函数。

为了让这些并发进程或线程在管程内互斥的执行,管程的实现必须隐含的具有锁或二值信号量。

如果没有条件变量,管程就不会有很有用,条件变量提供了一种对管程内并发协作进程的同步机制。

条件变量代表了管程中一些并发进程或线程可能要等待的条件。

一个条件变量管理着管程内的一个等待队列。

如果管程内某个进程或线程发现其执行条件为假,则该进程或线程就会被条件变量挂入管程内等待该条件的队列。

如果管程内另外的进程或线程满足了这个条件,则它会通过条件变量再次唤醒等待该条件的进程或线程,从而避免了死锁的产生。

所以,一个条件变量C应具有两种操作 C.wait()和C.signal()。

当管程内同时出现唤醒者和被唤醒者时,由于要求管程内的进程或线程必须互斥执行,因此就出现了两种样式的条件变量:Mesa Style(signal-and-continue): 唤醒者进程或线程继续执行,被唤醒者进程或线程等到唤醒者进程或线程阻塞或离开管程后再执行。

Hoare Style(signal-and-wait): 被唤醒者进程或线程立即执行,唤醒者进程或线程阻塞,直道被唤醒者阻塞或离开管程后再执行。

我们实验所做的就是在原来mesa样式的基础上进行Hoare样式的改进;这种样式也是我们实验中需要实现的样式。

2.设计目标验证并分析Nachos中Bridge管程是否能够正确的解决单行桥双向过桥问题。

定义和实现Hoare样式的条件变量Condition_H类利用Hoare样式的条件变量Condition_H,实现Ring类中定义的各个方法,使用Ring管程解决生产者/消费者问题。

生产者消费者问题Java三种实现

生产者消费者问题Java三种实现

⽣产者消费者问题Java三种实现⽣产者-消费者Java实现2017-07-271 概述⽣产者消费者问题是多线程的⼀个经典问题,它描述是有⼀块缓冲区作为仓库,⽣产者可以将产品放⼊仓库,消费者则可以从仓库中取⾛产品。

解决⽣产者/消费者问题的⽅法可分为两类:采⽤某种机制保护⽣产者和消费者之间的同步;在⽣产者和消费者之间建⽴⼀个管道。

第⼀种⽅式有较⾼的效率,并且易于实现,代码的可控制性较好,属于常⽤的模式。

第⼆种管道缓冲区不易控制,被传输数据对象不易于封装等,实⽤性不强。

在Java中有四种⽅法⽀持同步,其中前三个是同步⽅法,⼀个是管道⽅法。

wait() / notify()⽅法await() / signal()⽅法BlockingQueue阻塞队列⽅法PipedInputStream / PipedOutputStream本⽂只介绍前三种。

2 实现2.1 wait() / notify()⽅法wait() / nofity()⽅法是基类Object的两个⽅法:wait()⽅法:当缓冲区已满/空时,⽣产者/消费者线程停⽌⾃⼰的执⾏,放弃锁,使⾃⼰处于等等状态,让其他线程执⾏。

notify()⽅法:当⽣产者/消费者向缓冲区放⼊/取出⼀个产品时,向其他等待的线程发出可执⾏的通知,同时放弃锁,使⾃⼰处于等待状态。

缓冲区Storage.java代码如下:import java.util.LinkedList;public class Storage{// 仓库最⼤存储量private final int MAX_SIZE = 100;// 仓库存储的载体private LinkedList<Object> list = new LinkedList<Object>();// ⽣产产品public void produce(String producer){synchronized (list){// 如果仓库已满while (list.size() == MAX_SIZE){System.out.println("仓库已满,【"+producer+"】:暂时不能执⾏⽣产任务!");try{// 由于条件不满⾜,⽣产阻塞list.wait();}catch (InterruptedException e){e.printStackTrace();}}// ⽣产产品list.add(new Object());System.out.println("【"+producer+"】:⽣产了⼀个产品\t【现仓储量为】:" + list.size()); list.notifyAll();}}// 消费产品public void consume(String consumer){synchronized (list){//如果仓库存储量不⾜while (list.size()==0){System.out.println("仓库已空,【"+consumer+"】:暂时不能执⾏消费任务!");try{// 由于条件不满⾜,消费阻塞list.wait();}catch (InterruptedException e){e.printStackTrace();}}list.remove();System.out.println("【"+consumer+"】:消费了⼀个产品\t【现仓储量为】:" + list.size()); list.notifyAll();}}public LinkedList<Object> getList(){return list;}public void setList(LinkedList<Object> list){this.list = list;}public int getMAX_SIZE(){return MAX_SIZE;}}View CodeTest.javapublic class Test {public static void main(String[] args){Storage storage=new Storage();for(int i=1;i<6;i++){int finalI = i;new Thread(new Runnable() {@Overridepublic void run() {storage.produce(String.format("⽣成者%d:", finalI));}}).start();}for(int i=1;i<4;i++){int finalI = i;new Thread(()-> storage.consume(String.format("消费者%d:", finalI))).start();}}}View Code结果如下:仓库已空,【消费者1】:暂时不能执⾏消费任务!【⽣产者3】:⽣产了⼀个产品【现仓储量为】:1【消费者2】:消费了⼀个产品【现仓储量为】:0仓库已空,【消费者3】:暂时不能执⾏消费任务!【⽣产者1】:⽣产了⼀个产品【现仓储量为】:1【⽣产者4】:⽣产了⼀个产品【现仓储量为】:2【⽣产者2】:⽣产了⼀个产品【现仓储量为】:3【⽣产者5】:⽣产了⼀个产品【现仓储量为】:4【消费者1】:消费了⼀个产品【现仓储量为】:3【消费者3】:消费了⼀个产品【现仓储量为】:22.2 await() / signal()⽅法await()和signal()的功能基本上和wait() / nofity()相同,完全可以取代它们,但是它们和新引⼊的锁定机制Lock直接挂钩,具有更⼤的灵活性。

实验一生产者消费者问题

实验一生产者消费者问题

实验一生产者消费者问题一、实验目的1.掌握进程(线程)的同步与互斥。

2.掌握生产者消费者问题的实现方法。

3.掌握多线程编程方法。

二、相关函数VC提供一系列函数用于实现多线程编程以及线程的互斥与同步。

(1)创建线程HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:✧lpThreadAttributes:指向一个SECURITY_ATTRIBUTES 结构的指针,该结构决定了线程的安全属性,一般置为NULL;✧dwStackSize:指定了线程的堆栈深度,一般都设置为0;✧lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址。

main()函数是主线程的入口函数,同样,新创建的线程也需要一个入口函数,lpStartAddress 就是指示该函数的地址。

并且这个函数的定义应遵循下面的声明形式DWORD WINAPI ThreadProc(LPVOID lpParameter);✧lpParameter:指定了线程执行时传送给线程的32位参数,即线程函数的参数;✧dwCreationFlags:控制线程创建的附加标志,可以取两种值。

如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于阻塞状态,并不马上执行,直至函数ResumeThread被调用;✧lpThreadId:该参数返回所创建线程的ID;✧函数返回值:如果创建成功则返回线程的句柄,否则返回NULL。

生产者消费者问题设计实现分析

生产者消费者问题设计实现分析

操作系统课程设计任务书学院计算机与信息工程专业计算机科学与技术课程名称操作系统题目生产者消费者问题设计与实现完成期限自2015年6月23日至2015年6月29日共1周内容及任务一、项目的目的1.理生产者消费者问题基本概念和工作原理,以及实现技术;2.理解并掌握生产者消费者问题相关算法,以及它的实现方法;3.掌握在eclipse环境下,系统开发的基本步骤和方法;4.掌握在eclipse环境下,设计和开发一个简单的生产者消费者问题系统来模拟操作系统中生产者消费者问题。

二、项目任务的主要内容和要求1.精读并理解和掌握生产者消费者问题;2.编写程序来模拟生产者消费者问题的实现;3.编写应用程序测试生产者消费者问题,并显示结果。

三、项目设计(研究)思路本课程设计的基本思路是,首先理解和掌握生产者消费者问题的基本思想和原理,然后根据理解的基本思想和原理编程实现生产者消费者问题,最后通过数据分析生产者消费者问题。

四、具体成果形式和要求成果:生产者消费者问题程序语言实现;设计说明书。

要求:编写好的生产者消费者问题程序能够正确启动运行;设计说明书规范、合理。

进度安排起止日期工作内容2015.6.23至2015.6.24熟悉相关内容2015.6.25至2015.6.26 系统设计和实现2015.6.27至2015.6.29 系统实现和撰写相关文档主要参考资料1.《计算机操作系统》汤子瀛哲凤屏汤小丹主编西安电子科技大学出版社.2.《计算机操作系统概论》陈宏杨忠耀主编重庆邮电大学出版社.3.《计算机操作系统基本知识》廖成崔阳主编电子工业出版社.4.《操作系统实现与设计》陆刚望能主编电子工业出版社.5.《java程序语言设计》丁振凡主编,薛清华副主编清华大学出版社.指导教师意见(签字):年月日系(教研室)主任意见(签字):年月日目录1.选题背景 (1)2.设计思路 (1)3.过程讨论 (1)4.结果分析 (7)5.结论 (8)参考文献 (9)致谢 (10)附录 (10)指导教师评语........................ 错误!未定义书签。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

生产者消费者问题实现
班级姓名学号
一.实验目的
1.熟悉临界资源、信号量及PV操作的定义与物理意义
2.了解线程通信的方法
3.掌握线程互斥与同步的相关知识
4.掌握用信号量机制解决线程之间的同步与互斥问题
5.实现生产者-消费者问题,深刻理解线程同步问题
二、实验的硬件、软件平台
硬件:计算机
软件:操作系统win10
应用软件:Dev C++
三、实验原理
生产者-消费者问题是一个经典的线程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。

在同一个线程地址空间内执行的两个线程。

生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。

消费者线程从缓冲区中获得物品,然后释放缓冲区。

当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。

当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

多个生产/消费者在有界缓冲上操作。

它利用N个字节的共享内存作为有界循环缓冲区,利用写一字符模拟放一个产品,利用读一字符模拟消费一个产品。

当缓冲区空时消费者应阻塞睡眠,而当缓冲区满时生产者应当阻塞睡眠。

一旦缓冲区中有空单元,生产者线程就向空单元中入写字符,并报告写的内容和位置。

一旦缓冲区中有未读过的字符,消费者线程就从该单元中读出字符,并报告读取位置。

生产者不能向同一单元中连续写两次以上相同的字符,消费者也不能从同一单元中连续读两次以上相同的字符。

在进行多线程编程时,由于资源共享和进程间合作而造成进程间相互制约,难免还要碰到两个问题,那就线程间的互斥与同步:线程同步是指线程之间所具有的一种制约关系,一个线程的执行依赖另一个线程的消息,当它没有得到另一个线程的消息时应等待,直到消息到达时才被唤醒。

线程互斥是指对于共享的进程系统资源,在各单个线程访问时的排它性。

当有若干个线程都要使用某一共享资源时,任何时刻最多只允许一个线程去使用,其它要使用该资源的线程必须等待,直到占用资源者释放该资源。

线程互斥可以看成是一种特殊的线程同步(下文统称为同步)。

线程间的同步方法大体可分为两类:用户模式和内核模式。

内核模式就是指
利用系统内核对象的单一性来进行同步,使用时需要切换内核态与用户态,而用户模式就是不需要切换到内核态,只在用户态完成操作。

用户模式下的方法有:原子操作(例如一个单一的全局变量),临界区。

内核模式下的方法有:事件,信号量,互斥量。

在本实验中,线程之间要进行通信来操作同一缓冲区。

一般来说,线程间的通信可以划分为三种:1)使用全局变量实现线程间通信;2)使用消息实现线程间通信;3)使用CEvent类实现线程间通信。

四、实验内容及步骤
实验内容:模拟操作系统中进程同步和互斥。

实现经典同步问题:生产者—消费者,具体要求如下(可采用C++或者java)
(1)一个大小为10的缓冲区,初始状态为空。

(2)2个生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等
待消费者取走数据之后再添加,重复10次。

(3)2个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等
待生产者添加数据之后再读取,重复10次。

(4)按要求输出。

实验步骤:
首先,使用一个互斥锁,意味着资源槽机制就不能使用了。

因为资源槽虽以用一个互斥锁完成,但是需要有额外的通信,如果使用管道通信,则管道也必须是互斥,这就不满足1个互斥锁的要求。

其次,要求生产者一直生产,这就否定了另外一种方法:消费者、生产者的位置均平等,消费者消费的时候生产者不能生产,生产者生产的时候消费者不能消费。

因此,就需要采用A要求,也就是循环链表的形式。

为了保证互斥要求,需要定义一个数据结构,这个数据结构包含两个指针,一个读一个写,同时有一个资源数目量,告诉生产者和消费者是否可以生产或者消费。

由于该数据结构很小,因而可以对此结构互斥访问。

同时,对于每组数据,都有一个标志位,表示此组数据是否被占用,生产者和消费者均可以先占用此位置然后完成相应的操作。

当消费者互斥访问此结构时,首先判断是否有数据可以取,如果没有,直接等待,若有数据可取,先更改标志位占用此数据,并将资源数目-1。

然后交出互斥,把数据拷贝到自己缓冲区内,清空数据。

当生产者访问时,首先判断有没有空位可以生产,如果没有,直接等待,若有数据可以生产,先判断该位是否被占用,如果没被占用,则占用此位置进行生产。

生产完成后,将占用位改为未占用,同时将资源数目+1。

流程图: A 、主函数
Y
Y N
Y N
B 、统计线程
Y
N
Main 函数开始 初始化公共数据区
初始化信号量 创建生产者进程 创建消费者进程
创建统计进程 成功?
成功?
成功?
定时到 退出
开始进程 定时时间+1 满屏 打印消费结束进程
修改退出
C 、生产者线程 N
Y
Y
N
Y
N
N
Y
Y
开始进程
要求退出
结束进程
加锁成功
有空位
取得成功
加锁成功
生产数据
解锁
设置取得成功
失败计数+1
设置取得失败
检查资源数目
要求加锁
解锁
增加资源数目
要求加锁
D 、消费者线程
N
Y
N
N
N
N
Y
Y
五、实现代码
六、运行结果
开始进程
要求退出
结束进程
加锁成功
有产品
取得成功 加锁成功
消费数据
解锁
设置取得成功
失败计数+1
设置取得失败
检查资源数目
要求加锁
解锁
增加资源数目
要求加锁
七、实验心得
通过这次实验,我对linux的线程、进程等知识有了更直观深入的了解。

通过写这几个程序,弄清楚了信号量及互斥在使用中的具体运行方法。

除了涉及多个知识点之外,自己在做程序的时候也通过解决问题,对linux下一些函数认识的更加透彻,例如对进程间的通信,多线程的安全问题,管道问题都有了进一步的了解。

相关文档
最新文档