生产者消费者问题模拟实现(z)
生产者消费者实验报告
生产者消费者实验报告
生产者消费者实验报告
引言:
生产者消费者模型是计算机科学中的一个经典问题,用于解决多线程并发访问
共享资源的同步问题。在本实验中,我们通过编写一个简单的Java程序来模拟
生产者消费者模型,并观察其运行结果和效果。
一、实验背景
生产者消费者模型是一种常见的并发模型,用于解决多线程访问共享资源时可
能出现的数据竞争和同步问题。在该模型中,生产者负责生产数据并将其放入
共享缓冲区,而消费者则负责从缓冲区中取出数据进行消费。为了确保生产者
和消费者之间的同步与互斥,需要使用合适的同步机制,如信号量、互斥锁等。
二、实验目的
本实验的主要目的是通过编写一个简单的生产者消费者程序,验证该模型在多
线程环境下的正确性和效果。我们将通过观察程序的输出结果和运行时间来评
估其性能,并分析其中可能存在的问题和改进空间。
三、实验设计
1. 编写生产者类和消费者类:
我们首先定义了一个共享缓冲区,用于存储生产者生产的数据。然后,我们
编写了一个生产者类和一个消费者类,分别实现了生产者和消费者的逻辑。在
生产者类中,我们使用了一个循环来模拟生产者不断地生产数据,并将其放入
缓冲区。而在消费者类中,我们同样使用了一个循环来模拟消费者不断地从缓
冲区中取出数据进行消费。
2. 同步机制的选择:
为了保证生产者和消费者之间的同步与互斥,我们选择了信号量作为同步机制。在生产者类中,我们使用一个信号量来控制缓冲区的可用空间,当缓冲区已满时,生产者将等待,直到有可用空间。而在消费者类中,我们同样使用一个信号量来控制缓冲区的可用数据,当缓冲区为空时,消费者将等待,直到有可用数据。
操作系统实验报告生产者消费者问题
操作系统课程设计
一.实验目标
完成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生产者线程生产的产品。
生产者消费者问题模拟实现(z)
typedef struct semaphore
{
int value;
//信号量的值
struct pcb *list; //信号量队列的指针
}
信号量说明: semaphore s;
P、V 操作原语描述如下:
(1)P(s):s.value--;若 s.value≥0,则执行 P(s)的进程继续执
行;若 s.value<0,则执行 P(s)的进程被阻塞,并把它插入到等待信
#define processNum 4 //进程数量(生产者、消费者进程总数目)
struct DataBuffer
//缓冲区
{
int buffer[dataBufferSize];
int cou源自文库t; //当前产品数量
} dataBuffer;
(3)为解决生产者-消费者问题需设两个同步信号量:信号量 empty
(5)程序中主要数据结构和函数说明; (6)带注释的源程序代码; (7)程序运行结果及分析; (8)实验收获与体会。 1.2 预备知识 1.2.1 生产者—消费者问题 生产者—消费者问题表述如下:如图 3.1 所示,有 n 个生产者和 m 个消费者,连接在具 有 k 个单位缓冲区的有界环状缓冲上,故又称有界缓冲问题。生产者 不断生成产品,只要缓冲区未满,生产者进程 pi 所生产的产品就可 投入缓冲区;类似的,只要缓冲区非空,消费者进程 cj 就可以从缓 冲区取走并消耗产品。 图 3.1 生产者—消费者问题示意图 著名的生产者—消费者问题(producer-consumer problem)是计算 机操作系统中并发进程内在关系的一种抽象,是典型的进程同步问 题。在操作系统中,生产者进程可以是计算进程、发送进程,而消费 者进程可以是打印进程、接收进程等,解决好生产者—消费者问题就 解决了一类并发进程的同步问题。 操作系统实现进程同步的机制称为同步机制,它通常由同步原语组 成。不同的同步机制采用不同的同步方法,迄今已设计出多种同步机 制,本实验采用最常用的同步机制:信号量及 PV 操作。 1.2.2 信号量与 PV 操作
生产者消费者问题设计与实现汇编
生产者消费者问题设
计与实现
操作系统课程设计任务书
目录
操作系统课程设计任务书 (1)
1.选题背景 (1)
2.设计思路 (1)
2.1.生产者—消费者问题是一种同步问题的抽象描述。 (1)
2.2计算机系统中的每个进程都可以消费或生产某类资源。当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。 (1)
3.过程论述 (1)
4.结果分析 (7)
运行主程序得到一个GUI窗口,在文本域中输出结果,一共10个缓冲单元,三个生产者随机生产产品依次从0编号的缓冲区放入产品,消费者按照生产的先后顺序消费产品。 (7)
当缓冲单元有产品时,状态栏显示true,否则显示false。并且当消费者取走产品后,产品编号会变成0 (7)
5.结论 (8)
参考文献 (9)
致谢 (9)
附录 (10)
1.选题背景
生产者消费者问题是研究多线程程序时绕不开的经典问题之一,它描述是有一块缓冲区作为仓库,生产者可以将产品放入仓库,消费者则可以从仓库中取走产品。解决生产者/消费者问题的方法可分为两类:(1)采用某种机制保护生产者和消费者之间的同步;(2)在生产者和消费者之间建立一个管道。第一种方式有较高的效率,并且易于实现,代码的可控制性较好,属于常用的模式。第二种管道缓冲区不易控制,被传输数据对象不易于封装等,实用性不强。因此本文只介绍同步机制实现的生产者/消费者问题。
同步问题核心在于:如何保证同一资源被多个线程并发访问时的完整性。常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。Java语言在多线程编程上实现了完全对象化,提供了对同步机制的良好支持。在Java中一共有四种方法支持同步,其中前三个是同步方法,一个是管道方法。
(完整word版)生产者-消费者问题
课程设计报告
课程名:操作系统
专业
学生姓
名
班级
学号
指导教
师
完成日
期
博雅学院
“操作系统”课程设计报告
-—生产者—消费者问题的模拟实现
1.课程设计的目的
本课程设计是学习完“操作系统原理”课程后进行的一次全面的综合训练,通过课程设计,更好地掌握操作系统的原理及实现方法,加深对操作系统基础理论和重要算法的理解,加强学生的动手能力。
2.设计内容
2.1 概述
用多进程同步方法解决生产者-消费者问题,C或C++语言实现。
通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制。
说明:有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数.
设计要求:(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者县城的标识符。(2)生产者和消费者各有两个以上。(3)多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码。
2.2 设计原理
多进程是一种非常简洁的多任务操作方式。在Linux系统下,启动一个新的进程必须分配给它独立的地址空间,建立众多的数据表来维护它的代码段、堆栈段和数据段,这是一种烦琐的多任务工作方式。
生产者-消费者方案是多进程应用程序开发中最常用的构造之一。因此困难也在于此。因为在一个应用程序中可以多次重复生产者—消费者行为,其代码也可以如此。设计中创建了Consumer 类,该类通过在一些多进程应用程序中促进代码重用以及简化代码调试和维护来解决这个问题。多进程应用程序通常利用生产者—消费者编程方案,其中由生产者进程创建重复性作业,将其传递给作业队列,然后由消费者进程处理作业.
labview学习——生产者消费者(数据)(事件)
labview学习——⽣产者消费者(数据)(事件)
其主要的模型:
主要从以下⼏个⽅⾯理解:
1、可重⼊性
正常的labview是多线程设计语⾔,⽽我们在执⾏VI时的规则是通过VI的命名来分别调⽤实现的。
打开VI的Highlight调试⼯具,可以看出两个Wait.vi实例的调⽤并不是同时执⾏的,⽽是依次按顺序执⾏的,⾄于哪⼀个实例先执⾏是不确定的。这是由于LabVIEW本⾝是并⾏设计的,从理论上⽽⾔,两个VI的实例是同步执⾏的,但是如果两个Wait.vi实例同时执⾏必定会产⽣参数赋值紊乱,因为LabVIEW只允许内存中存在⼀个名称的VI。
如果在⼀个顺序结构⾥要同时进⾏两个vi的调⽤,采⽤的⽅法是单击ctrl+I,在新点出来的对话框中选择执⾏框⾥边的可重⼊选择Reentrant execution,这样的话再次运⾏上述实例⽤时长为并⾏执⾏的时间。事实上,LabVIEW的可重⼊技术相当于在原有VI的基础上产⽣了⼀个相同的副本,打开Wait.vi从标题栏可以看出VI的名称为Wait.vi:1(clone)。同理这是由于LabVIEW中不允许内存中的VI存在同名,VI的可重⼊技术相当于产⽣了与原VI具有同样功能的新VI并且修改了该VI的命名。
在实际应⽤中,需要根据情况决定是否设置VI的可重⼊属性,灵活使⽤。并不是需要将所有的VI都设置为可重⼊,那将占据⼤量的内存资源。
2、动态调⽤
通常调⽤⼦VI有两种⽅法,⼀种是静态调⽤,直接在控制板⾥选择⼦VI的⽅法,即编译⽣成可执⾏程序后,⼦VI的代码将会被静态链接到可执⾏程序中
实验二生产者消费者问题实践
实验二生产者消费者问题实践
【实验目的】
配合操作系统课程的学习,加深对生产者与消费者问题的理解并熟悉VC的使用。
【实验学时】
建议2学时
【实验内容】
利用信号量机制完成5个生产者10个消费者的同步。
【实验原理】
生产者消费者问题是把并发进程的同步和互斥问题一般化后得到的一个抽象的一般模型。首先同步问题:消费者只有在有界缓冲区内有数据的时候才能进行消费,而生产者只能在有界缓冲区内有空间的时候才能够进行生产。其次,由于有界缓冲区是临界资源,所以生产者进程和消费者进程必须互斥。
为此,本实验中设置了一个公用的信号量即“ct”用来保证互斥的实现,它的初始值为1。另外为生产者和消费者分别设置了两个私用信号量,分别为“notem”和“notfu”。其中“notfu”表示有界缓冲区中的空单元数,初始值为20;“notem”表示有界缓冲区中非空单元数,初始值为0。
由于信号量的值只能通过P、V原语来操作,所以本实验中还定义了P、V的有关操作。【实验要求】
实现生产者、消费者的模拟函数(produce、consume),用它们来模拟生产者消费者问
题。
【实验步骤】
1、创建一个控制台类型的、名为P_C的工程(如图5-1所示)。下一步选择简单应用(如图
5-2所示)。
2、在P_C.cpp文件中添加如下代码:
3、添加一个类,用于控制生产者消费者的状态。点击Insert->New Class.类名为"Monitor"
(如图5-3 所示)。
4、在Monitor.h 文件中添加如下代码:
5、在Monitor.cpp文件中添加如下代码:
生产者与消费者问题(附源码)
操作系统实验报告
专业网络工程班级08102 学号姓名
课程名称操作系统学年2010-2011 学期下
课程类别专业必修■限选□任选□实践□实验时间2010年11月3日
实验名称
实验一:生产者与消费者问题
实验目的和要求
全面理解生产者与消费者问题模型,掌握解决该问题的算法思想,正确使用同步机制。
实验软硬件要求
Pentium ||| 450以上CPU 64MB以上内存
WINDOWS XP
Visual C++6.0
实验内容、方法和步骤(可附页)
问题描述:一组生产者向一组消费者提供商品,共享一个有界缓冲池,生产者向其中放入商品,消费者从中取得商品。假定这些生产者和消费者互相等效,只要缓冲池未满,生产者可将商品送入缓冲池;只要缓冲池未空,消费者可从缓冲池取走一商品。
功能要求:根据进程同步机制,编写一个解决上述问题的程序,可显示缓冲池状态、放商品、取商品等过程。
具体参数:3个生产者进程,2个消费者进程;
缓冲区单元个数N=4;
在本程序中是缓冲区中的数从0变为1表示模拟生产一个产品,消费时则将对应缓冲区内的1变为0,为模拟消费一个产品。
实验结果(可附页)
见截图
小结
这次多线程的操作系统实验,使我对线程的概念以及多线程程序中线程间的运行有了更深的认识,同时也让我的编程能力得到了一定的提高。
这次做的用多线程实现生产者与消费者模型的实验,由于我的编程能力基础比较差,对线程也是一无所知,所以一开始觉得无从下手,但幸好老师给了充足的时间,我通过看网上找的视频资料以及请教同学才渐渐地有了一点概念,然后我试着从网上下了一些多线程的程序分析里面的语句,基本弄懂了多线程的原理。
生产者消费者问题
⽣产者消费者问题
⽣产者消费者问题
背景
在并发编程中,⽣产者消费者问题(producer/consumer)是⼀个经典的⽼⽣常谈的问题,有时也称为有界缓冲区问题。
问题的基本背景假设是:我们有⼀个固定⼤⼩的缓冲区,这个缓冲区分别有两种⼯作性质不同的线程去操作。其中⼀种线程负责向缓冲区中写⼊数据,我们称之为⽣产者线程。另⼀种线程则负责从缓冲区中拿取数据,并称之为消费者线程。
同时两种线程的写⼊和拿取⼯作要遵循⼀定的规则:
1. 缓冲区未写满时,⽣产者线程可以向缓冲区中写⼊数据。但是消费者线程不能从缓冲区中读取数据。
2. 缓冲区写满时,⽣产者线程不能向缓冲区中写⼊数据,消费者线程可以冲缓冲区中读取数据。
3. 不管是那种性质的线程,在操作缓冲区时,均不可出现并发安全问题。
分析可以得知,解决⽣产者消费者问题,其实就是要解决线程同步问题与共享资源互斥访问问题。互斥问题的解决可以借助锁来实现,⽽线程同步则需借助信号量或其他⼯具来实现。
Java实现
class FixedSizeBuffer
{
private static final int DEFAULT_BUFFER_SIZE = 1024;
private final ReentrantLock lock = new ReentrantLock(); // 共享资源访问锁
private final Condition isFull = lock.newCondition(); // buffer是否已满
private final Condition isEmpty = lock.newCondition(); // buffer是否还空着
生产者消费者问题
生产者-消费者(producer-consumer)问题,也称作有界缓冲区(bounded-buffer)问题,两个进程共享一个公共的固定大小的缓冲区。其中一个是生产者,用于将消息放入缓冲区;另外一个是消费者,用于从缓冲区中取出消息。问题出现在当缓冲区已经满了,而此时生产者还想向其中放入一个新的数据项的情形,其解决方法是让生产者此时进行休眠,等待消费者从缓冲区中取走了一个或者多个数据后再去唤醒它。同样地,当缓冲区已经空了,而消费者还想去取消息,此时也可以让消费者进行休眠,等待生产者放入一个或者多个数据时再唤醒它。听起来好像蛮对的,无懈可击似的,但其实在实现时会有一个竞争条件存在的。为了跟踪缓冲区中的消息数目,需要一个变量 count。如果缓冲区最多存放 N 个消息,则生产者的代码会首先检查 count 是否达到 N,如果是,则生产者休眠;否则,生产者向缓冲区中放入一个消息,并增加 count 的值。消费者的代码也与此类似,首先检测 count 是否为 0,如果是,则休眠;否则,从缓冲区中取出消息并递减 count 的值。同时,每个进程也需要检查是否需要唤醒另一个进程。代码可能如下:// 缓冲区大小#define N 100 int count = 0; // 跟踪缓冲区的记录数/* 生产者进程 */void procedure(void){int item; // 缓冲区中的数据项while(true) // 无限循环{ item = produce_item(); // 产生下一个数据项if (count == N) // 如果缓冲区满了,进行休眠{sleep();}insert_item(item); // 将新数据项放入缓冲区count = count + 1; // 计数器加 1if (count == 1) // 表明插入之前为空,{ // 消费者等待wakeup(consumer); // 唤醒消费者}}}/* 消费者进程 */void consumer(void){int item; // 缓冲区中的数据项while(true) // 无限循环{if (count == 0) // 如果缓冲区为空,进入休眠{sleep();}item = remove_item(); // 从缓冲区中取出一个数据项count = count - 1; // 计数器减 1if (count == N -1) // 缓冲区有空
《操作系统概论》实验指导书-实验二 经典的生产者—消费者问题
实验二经典的生产者—消费者问题
一、目的
实现对经典的生产者—消费者问题的模拟,以便更好的理解经典进程同步问题。
二、实验内容及要求
编制生产者—消费者算法,模拟一个生产者、一个消费者,共享一个缓冲池的情形。
1、实现对经典的生产者—消费者问题的模拟,以便更好的理解此经典进程同步问题。生产者-消费者问题是典型的PV操作问题,假设系统中有一个比较大的缓冲池,生产者的任务是只要缓冲池未满就可以将生产出的产品放入其中,而消费者的任务是只要缓冲池未空就可以从缓冲池中拿走产品。缓冲池被占用时,任何进程都不能访问。
2、每一个生产者都要把自己生产的产品放入缓冲池,每个消费者从缓冲池中取走产品消费。在这种情况下,生产者消费者进程同步,因为只有通过互通消息才知道是否能存入产品或者取走产品。他们之间也存在互斥,即生产者消费者必须互斥访问缓冲池,即不能有两个以上的进程同时进行。
三、实验环境
操作系统环境:Windows或DOS系统。
编程语言:Turbo C、Visual C++、broland C++、Visual Basic、Delphi、Java等。
四、实验思路和设计
1、程序流程图
由学生完成。
2、主要程序代码
//初始化变量
Private Sub Form1_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
mutex = 1 //互斥信号量
full = 0 //缓冲池中满缓冲区的数量
操作系统生产者与消费者实验报告
实验报告
第页
专业_______软件工程_____ 班级_________ 学号_____ 姓名
实验日期:年月日报告退发(订正、重做)
课程实验名称生产者与消费者问题、读者—写者问题
一、实验目的
1. 实现生产者消费者问题模拟
2. 进一步掌握P,V如何解决同步和互斥问题
二、实验环境
1. Windows或Linux平台
2. Eclipse、Visual Studio 2005或GCC
三、实验内容、步骤和结果分析
实验内容:
实现生产者消费者问题模拟,显示每次添加和读取数据时缓冲区的状态,
生产者和消费者可用线程模拟。
1.一个大小为10的缓冲区,初始为空。
2. 五个生产者:若缓冲区可以加入数据,则示意进入生产过程(打印出生产者ID),往缓冲区添加数据,随机等待一段时间。若缓冲区已满,等待消费者取走数据后再添加。
3. 五个消费者:若缓冲区可以读取数据,则示意进入消费过程(打印出消费者ID),从缓冲区读取数据,随机等待一段时间;若缓冲区为空,等待生产者添加数据后再读取。
四、讨论
(说明实验过程中遇到的问题及解决办法;未解决/需进一步研讨的问题或建议新实验方法等)
(请利用实验二中所给的各个版本信号量类来完成实验三。若选用Windows平台,要求一定要选用这三个文件夹中的某个信号量类Semaphore来完成实验,否则实验报告视为缺交;若选用Linux平台,也要求参照已给出的三个版本的Semaphore类的接口,先定义一个Linux版本的C++类class Semaphore,并在该类基础上完成实验,提交实验报告时请附上自定义的Semaphore类。
1实验1:生产者消费者问题
福建农林大学金山学院实验报告
系(教研室):专业:计算机科学与技术年级:
实验课程:生产者与消费者实验姓名:学号:
实验室号:1#608
计算机号:实验时间:指导教师签字: 成绩:
实验1:生产者消费者问题
一、实验目的
生产者消费者问题是操作系统中经典的同步和互斥问题.通过实验,要求学生掌握两者之间的同步信号量和互斥信号量的使用,更深刻了解临界资源、同步和互斥的概念。
二、实验要求
1.一组生产者通过一个具有N个缓冲区的缓冲池循环不断地向一组消费者提供产
品。
2.建一个队列, 队列的长度由n记录, 定义两个指针,分别指向队列的头和尾消
费者从头指针读取数据,每读取一个数据把n——,生产者把数据写入尾指针,
每写入一个数据就n++,当n=N的时候生产者暂停写入数据.
3.注意:缓冲池队列,用互斥锁保护.
三、实验内容和原理
1.分别画出生产者和消费者的流程图
2.针对生产者和消费者问题,可以分为哪几种情况,使用了哪些原语?分别代表什
么意思?过程如何?阐述哪些进程之间存在同步,哪些进程之间存在互斥.
3.缓冲区是否为临界资源?是否可以循环使用?通过什么来实现?举例说明(可
画图)
四、实验环境
1. 硬件:PC机;
2. 软件:Windows操作系统、VC6。0。
五、算法描述及实验步骤
#include <windows.h〉
#include 〈iostream>
const unsigned short SIZE_OF_BUFFER = 10;
unsigned short ProductID = 0;
unsigned short ConsumeID = 0;
生产者消费者问题实现
A、主函数
Y
成功?
0
创建消费者进程
成功?
创建统计进程
退出
B、统计线程
开始进程
修改退出
结束进程
四、实验内容及步骤
实验内容:模拟操作系统中进程同步和互斥。
实现经典同步问题:生产者一消费者,具体要求如下(可采用C++或者java)
(1)一个大小为10的缓冲区,初始状态为空。
⑵2个生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等 待消费者取走数据之后再添加,重复10次。
(3)2个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等
待生产者添加数据之后再读取,重复10次。
(4)按要求输出。
实验步骤:
首先,使用一个互斥锁,意味着资源槽机制就不能使用了。因为资源槽虽以 用一个互斥锁完成,但是需要有额外的通信,如果使用管道通信,则管道也必须 是互斥,这就不满足1个互斥锁的要求。其次,要求生产者一直生产,这就否定 了另外一种方法:消费者、生产者的位置均平等,消费者消费的时候生产者不能 生产,生产者生产的时候消费者不能消费。因此,就需要采用A要求,也就是循
多个生产/消费者在有界缓冲上操作。它利用N个字节的共享内存作为有界 循环缓冲区,利用写一字符模拟放一个产品,利用读一字符模拟消费一个产品。 当缓冲区空时消费者应阻塞睡眠,而当缓冲区满时生产者应当阻塞睡眠。一旦缓 冲区中有空单元,生产者线程就向空单元中入写字符,并报告写的内容和位置。 一旦缓冲区中有未读过的字符,消费者线程就从该单元中读出字符,并报告读取 位置。生产者不能向同一单元中连续写两次以上相同的字符,消费者也不能从同
实现生产者消费者(Bounded Buffer Problem)
目录
1设计题目与要求 (1)
1.1课程设计题目 (1)
1.2课程设计要求 (1)
2总体设计 (1)
2.1设计背景 (1)
2.2设计思想 (2)
2.2.1创建一个线程 (2)
2.2.2信号量 (2)
2.2.3设计原理 (3)
2.3开发工具的选择 (4)
2.4数据结构和模块说明 (4)
2.4.1主函数 (5)
2.4.2生产者线程函数 (6)
2.4.3消费者线程函数 (7)
3详细设计 (7)
3.1源程序 (7)
4运行结果与运行情况 (15)
5调试记录 (26)
6自我评析和总结 (26)
参考文献 (27)
实现生产者消费者(Bounded–Buffer
Problem)问题
1设计题目与要求
1.1课程设计题目
实现生产者消费者(Bounded–Buffer Problem)问题。
1.2课程设计要求
通过研究Linux的线程机制和信号量实现生产者消费者(Bounded Buffer)问题的并发控制。
实验条件要求:每人一台与Linux主机联网的Windows主机,普通用户权限。
(1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容、当前指针位置和生产者/消费者线程的标识符。
(2)生产者和消费者各有两个以上。
(3)多个生产者或多个消费者之间须共享对缓冲区进行操作的函数代码。
2总体设计
2.1设计背景
Linux系统下的多线程遵循POSIX线程接口,称为pthread。编写Linux下的多线程程序,需要使用头文件pthread.h,连接时需要使用库libpthread.a。顺便说一下,Linux 下pthread的实现是通过系统调用clone()来实现的。clone()是Linux所特有的系统调用,它的使用方式类似fork。
生产者和消费者问题
生产者和消费者问题
一、生产者和消费者问题
1、有n个缓冲区,一个生产者和一个消费者情况:
main ()
{ int S=1; //可否进入缓冲区
int full=0; //产品数目
int empty=n //可用缓冲区数
int buffer[n];
int in=0; //指向下一个可放产品的缓冲区
int out=0; //指向下一个可取产品的缓冲区producer();
consumer();
}
producer()
{
While(生产未结束)
{ produce a product
P(empty);
P(S);
Buffer[in]= product;
in=(in+1)mod n;
V(S);
V(full);
}
}
consumer()
{
While(消费未结束)
{ P(full);
P(S);
Take a product from Buffer[out]
Out=(out+1)mod n;
V(S);
V(empty);
}
Consume the product
}
2、m个生产者和k个消费者共享n个缓冲区的情况:
main()
{
int B[n]; //缓冲区
int p=r=0; //p表示生产者指针,r表示消费者指针int S=1; //可否进入缓冲区
int full=0; //产品数目
int empty=n; //可用缓冲区数
producer-i(i=1,2,…,m);
consumer-j(j=1,2,…,k);
}
Producer-i(i=1,2,…,m)
{
while (producing does not end )
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
生产者-消费者实验
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)是计算机操作系统中并发进程内在关系的一种抽象,是典型的进程同步问题。在操作系统中,生产者进程可以是计算进程、发送进程,而消费者进程可以是打印进程、接收进程等,解决好生产者—消费者问题就解决了一类并发进程的同步问题。
操作系统实现进程同步的机制称为同步机制,它通常由同步原语组成。不同的同步机制采用不同的同步方法,迄今已设计出多种同步机制,本实验采用最常用的同步机制:信号量及PV操作。
1.2.2信号量与PV操作
1965年,荷兰计算机科学家E.W.Dijkstra提出新的同步工具——信号量和PV操作,他将交通管制中多种颜色的信号灯管理方法引入操作系统,让多个进程通过特殊变量展开交互。一个进程在某一关键点上被迫停止直至接收到对应的特殊变量值,通过这一措施任何复杂的进程交互要求均可得到满足,这种特殊变量就是信号量(semaphore)。为了通过信号量传送信号,进程可利用P和V两个特殊操作来发送和接收信号,如果协作进程的相应信号仍未到达,则进程被挂起直至信号到达为止。
在操作系统中用信号量表示物理资源的实体,它是一个与队列有关的整型变量。具体实现时,信号量是一种变量类型,用一个记录型数据结构表示,有两个分量:一个是信号量的值,另一个是信号量队列的指针。信号量在操作系统中主要用于封锁临界区、进程同步及维护资源计数。除了赋初值之外,信号量仅能由同步原语PV对其操作,不存在其他方法可以检查或操作信号量,PV操作的不可分割性确保执行的原子性及信号量值的完整性。利用信号量和PV操作即可解决并发进程竞争问题,又可解决并发进程协作问题。
信号量按其用途可分为两种:公用信号量,联系一组并发进程,相关进程均可在此信号量上执行PV操作,用于实现进程互斥;私有信号量,联系一组并发进程,仅允许此信号量所拥有的进程执行P操作,而其他相关进程可在其上执行V操作,初值往往为0或正整数,多用于并发进程同步。
信号量的定义为如下数据结构:
typedef struct semaphore
{
int value; //信号量的值
struct pcb *list; //信号量队列的指针
}
信号量说明: semaphore s;
P、V操作原语描述如下:
(1)P(s):s.value--;若s.value≥0,则执行P(s)的进程继续执行;若s.value<0,则执行P(s)的进程被阻塞,并把它插入到等待信号量s的阻塞队列中。
(2)V(s):s.value++;若s.value≤0,则执行V(s)的进程从等待信号量s的阻塞队列中唤醒头一个进程,然后自己继续执行。若s.value>0 ,则执行V(s)
的进程继续执行;
1.2.3信号量实现互斥
信号量和PV操作可用来解决进程互斥问题。为使多个进程能互斥地访问某临界资源,只需为该资源设置一互斥信号量mutex,并置初值为1,然后将各进程访问该资源的临界区置于P(mutex)和V(mutex)操作之间即可。
用信号量和PV操作管理并发进程互斥进入临界区的一般形式为:
semaphore mutex;
mutex = 1;
cobegin
process Pi() /*i = 1,2, …,n */
{
P(mutex);
/*临界区*/
V(mutex);
}
coend
当有进程在临界区中时,mutex的值为0或负值,否则mutex值为1,因为只有一个进程,可用P操作把mutex减至0,故可保证互斥操作,这时试图进入临界区的其它进程会因执行P(mutex)而被迫等待。mutex的取值范围是1~-(n-1),表明有一个进程在临界区内执行,最多有n-1个进程在信号量队列中等待。
1.2.4信号量解决生产者—消费者问题
信号量和PV操作不仅可以解决进程互斥问题,而且是实现进程同步的有力工具。在协作进程之间,一个进程的执行依赖于协作进程的信息或消息,在尚未得到来自协作进程的信号或消息时等待,直至信号或消息到达时才被唤醒。
生产者—消费者问题是典型的进程同步问题,对于生产者进程:生产一个产品,当要送入缓冲区时,要检查是否有空缓冲区,若有,则可将产品送入缓冲区,并通知消费者进程;否则,等待;对于消费者进程:当它去取产品时,要看缓冲区中是否有产品可取,若有则取走一个产品,并通知生产者进程,否则,等待。这种相互等待,并互通信息就是典型的进程同步。
因此应该设两个同步信号量:信号量empty表示可用的空缓冲区的数目,初值为k;信号量full表示可以使用产品的数目,初值为0。
缓冲区是一个临界资源,必须互斥使用,所以另外还需要设置一个互斥信号量mutex,其初值为1。
用信号量机制解决生产者—消费者问题可描述如下:
item B[k];
semaphore empty; empty=k; //可以使用的空缓冲区数
semaphore full; full=0; //缓冲区内可以使用的产品数
semaphore mutex; mutex=1; //互斥信号量
int in=0; //放入缓冲区指针
int out=0; //取出缓冲区指针
cobegin
process producer_i() process consumer()
{ {
While(true) While(true)
{ {
produce(); P(full);
P(empty); P(mutex);
P(mutex); take from
B[out];
append to B[in]; out =
(out+1)%k;
in = (in+1)%k; V(mutex);
V(mutex); V(empty);
V(full);
consume();
} } } } Coend