进程同步模拟设计.docx
- 文档编号:25402028
- 上传时间:2023-06-08
- 格式:DOCX
- 页数:21
- 大小:446.01KB
进程同步模拟设计.docx
《进程同步模拟设计.docx》由会员分享,可在线阅读,更多相关《进程同步模拟设计.docx(21页珍藏版)》请在冰豆网上搜索。
进程同步模拟设计
进程同步模拟设计
——生产者和消费者问题
1.模拟用信号量机制实现生产者和消费者问题
1.1用信号量机制实现生产者和消费者
生产者消费者
1.1.1问题描述:
一组生产者向一组消费者提供消息,它们共享一个有界缓冲区n,生产者向其中输入消息,消费者从中取得消息。
1.1.2实现规则:
①对于生产者进程:
产生一个数据,当要送入缓冲区时,要检查缓冲区是否已满,若未满,则可将数据送入缓冲区,并通知消费者进程;否则,等待;
②对于消费者进程:
当它去取数据时,要看缓冲区中是否有数据可取,若有则取走一个数据,并通知生产者进程,否则,等待。
③缓冲区是个临界资源,因此,诸进程对缓冲区的操作程序是一个共享临界区,所以,还有个互斥的问题。
1.1.3具体进程描述:
full:
缓冲区产品数目,初值为0;
empty:
缓冲区可存放产品的空位;初值为n;
Mutex:
对缓冲区互斥信号灯,初值为1。
main()producer()consumer()
{{{
intfull=0,empty=n;while(生产未完成)while(还要继续消费)
intmutex=1;{...;{
cobeginp(empty);p(full);
producer();p(mutex);p(mutex);
consumer();生产一个产品;取出一个产品;
coend将产品放入缓冲区;消费一个产品;
}v(mutex);v(mutex);
v(full);v(empty);
}...;}
}}
1.2C++语言程序模拟用信号量机制实现生产者和消费者问题
定义一个整数型指针:
int*elements;并动态建立其大小:
elements=newint[n];用这个整型数组来表示缓冲区n,其中数组中每个元素为1或0(1表示有一个产品,0表示没有)。
该数组封装在SeqSquare的类中,作为其私有成员之一,对其操作的方法都是该类的成员函数:
voidP(intx);voidV(intx);boolIsEmpty();boolIsFull();
生产者和消费者的操作分别用函数voidproducer(SeqSquare*a)和voidconsumer(SeqSquare*a)实现,它们操作的对象都是类SeqSquare的对象。
2.实验报告内容及说明
2.1课程设计目的与功能
2.1.1设计目的:
通过实验模拟生产者与消费者之间的关系,了解并掌握他们之间的关系及其原理。
由此增加对进程同步的问题的了解。
具体如下:
(一)掌握基本的同步互斥算法,理解生产者和消费者模型
(二)了解windows中多线程(多进程)的并发执行机制,线程(进程)间的同步和互斥
(三)学习使用windows中基本的同步对象,掌握相应的API
2.1.2设计功能:
模拟完成:
当缓冲区未满时,生产者进程可生产产品,生产完成后放入一个缓冲区;当缓冲区未空时,消费者进程可从缓冲区内按次序取走产品去消费。
且生产者与消费者进程间实现并发执行。
2.2需求分析,数据结构或模块说明(功能与框图);
2.2.1类SeqSquare:
如1.2小节中的描述类SeqSquare的声明及其中一些成员函数如下:
classSeqSquare{
public:
SeqSquare(intn);
~SeqSquare(){deleteelements;}
voidP(intx);//p操作
voidV(intx);//v操作
voiddeca(){a--;}
voiddecb(){b--;}
boolIsEmpty(){return(top==-1)?
true:
false;}//empty
boolIsFull(){return(top>=maxSize-1)?
true:
false;}//full
intgetSize(){returntop+1;}
intgetmaxSize(){returnmaxSize;}
intgettop(){returntop;}
intgeta(){returna;}
intgetb(){returnb;}
private:
int*elements;
inttop,a,b;
intmaxSize;
};
2.2.2生产者和消费者操作以及显示缓冲区函数showbuf:
如1.2小节描述的voidproducer(SeqSquare*a)和voidconsumer(SeqSquare*a):
voidproducer(SeqSquare*a)
{
a->P
(1);
}//生产者操作
voidconsumer(SeqSquare*a)
{
a->V
(1);
}//消费者操作
显示缓冲区(即临界区)使用情况函数showbuf:
voidshowbuf(SeqSquare*a)
{
inti=a->getSize();
cout<<"临界区已占用"<getmaxSize()< } 2.2.3程序流程图 2.3源程序的主要部分 2.3.1类SeqSquare中各成员函数的实现: SeqSquare: : SeqSquare(intn) { top=-1; a=b=0; maxSize=n; elements=newint[maxSize];//数组的定义 } voidSeqSquare: : P(intx) { if(IsFull()==true) { cout<<"操作失败,临界区已满! "< a=a+1; } else { elements[++top]=x; cout<<"成功生产出一件产品! "< } } voidSeqSquare: : V(intx) { if(IsEmpty()==true) { cout<<"操作失败,临界区为空! "< b=b+1; } else { x=elements[top--]; cout<<"成功消费一件产品! "< } } 2.3.2主函数main(): voidmain() { ofstreamfout; fout.open("processing.txt");//输出文件 inti=1,n; cout<<"缓冲区的大小为: "< cin>>n; fout<<"缓冲区的大小为: "< fout< SeqSquare*s; s=newSeqSquare(n); while(i) { cout< cout<<"**************************************************"< cout<<"1: 生产一件产品;2: 消费一件产品;3: 显示缓冲区状态;"< cout<<"4: 缓冲区大小有所改变;0: 退出程序。 "< cout<<"**************************************************"< cout<<"请选择您的操作: "; cin>>i; fout< fout<<"**************************************************"< fout<<"1: 生产一件产品;2: 消费一件产品;3: 显示缓冲区状态;"< fout<<"4: 缓冲区大小有所改变;0: 退出程序。 "< fout<<"**************************************************"< fout<<"请选择您的操作: "; fout< switch(i) { case0: cout<<"成功退出程序! "< fout<<"成功退出程序! "< break; case1: producer(s); if(s->geta()==0) fout<<"成功生产出一件产品! "< else { fout<<"操作失败,临界区已满! "< s->deca(); } break; case2: consumer(s); if(s->getb()==0) fout<<"成功消费一件产品! "< else { fout<<"操作失败,临界区为空! "< s->decb(); } break; case3: showbuf(s); fout<<"临界区已占用"< break; case4: deletes; cout< cout<<"另一种不同产品的缓冲区的大小为: "< cin>>n; fout< fout<<"另一种不同产品的缓冲区的大小为: "< fout< s=newSeqSquare(n); break; default: cout<<"请输入正确的菜单项进行操作! "< fout<<"请输入正确的菜单项进行操作! "< } } } 3.运行结果与运行情况分析 3.1命令提示符窗口运行过程: 某一种产品缓冲区n大小为2: 选择操作1生产一个产品: 继续选择操作3显示缓冲区状态: 此时已经显示出生产者的功能即生产一个产品并放入缓冲区。 然后选择操作2消费一件产品: 继续选择操作3显示此时缓冲去状态: 此时已经显示出消费者的功能即从缓冲区去一个产品并消费一个产品。 然后选择操作2消费一个产品: 此时可以看到显示文字“操作失败,临界区为空! ”即可看出当缓冲区未空时,消费者进程可从缓冲区内按次序取走产品去消费。 然后连续两次选择操作1生产一个产品: 继续选择一次操作1生产一个产品: 此时可以看到显示文字“操作失败,临界区已满! ”即可看出当缓冲区未满时,生产者进程可生产产品,生产完成后放入一个缓冲区。 任意输入数值(除0,1,2,3,4。 比如5): 此时可以看到显示文字“请输入正确的菜单项进行操作! ”。 重新输入数值(0~4)即可继续运行。 然后选择操作4缓冲区大小有所改变,即另一个产品缓冲区n为3: 继续选择其他操作数进行操作,最后选择操作0退出程序: 3.2文件processing.txt: processing.txt文件记录了命令提示符窗口中所做的所有动作: 3.3程序的源代码 #include"stdafx.h" #include #include #include usingnamespacestd; classSeqSquare{ public: SeqSquare(intn); ~SeqSquare(){deleteelements;} voidP(intx);//p操作 voidV(intx);//v操作 voiddeca(){a--;} voiddecb(){b--;} boolIsEmpty(){return(top==-1)? true: false;}//empty boolIsFull(){return(top>=maxSize-1)? true: false;}//full intgetSize(){returntop+1;} intgetmaxSize(){returnmaxSize;} intgettop(){returntop;} intgeta(){returna;} intgetb(){returnb;} private: int*elements; inttop,a,b; intmaxSize; }; voidproducer(SeqSquare*a) { a->P (1); }//生产者操作 voidconsumer(SeqSquare*a) { a->V (1); }//消费者操作 voidshowbuf(SeqSquare*a) { inti=a->getSize(); cout<<"临界区已占用"<getmaxSize()< } SeqSquare: : SeqSquare(intn) { top=-1; a=b=0; maxSize=n; elements=newint[maxSize];//数组的定义 } voidSeqSquare: : P(intx) { if(IsFull()==true) { cout<<"操作失败,临界区已满! "< a=a+1; } else { elements[++top]=x; cout<<"成功生产出一件产品! "< } } voidSeqSquare: : V(intx) { if(IsEmpty()==true) { cout<<"操作失败,临界区为空! "< b=b+1; } else { x=elements[top--]; cout<<"成功消费一件产品! "< } } voidmain() { ofstreamfout; fout.open("processing.txt");//输出文件 inti=1,n; cout<<"缓冲区的大小为: "< cin>>n; fout<<"缓冲区的大小为: "< fout< SeqSquare*s; s=newSeqSquare(n); while(i) { cout< cout<<"**************************************************"< cout<<"1: 生产一件产品;2: 消费一件产品;3: 显示缓冲区状态;"< cout<<"4: 缓冲区大小有所改变;0: 退出程序。 "< cout<<"**************************************************"< cout<<"请选择您的操作: "; cin>>i; fout< fout<<"**************************************************"< fout<<"1: 生产一件产品;2: 消费一件产品;3: 显示缓冲区状态;"< fout<<"4: 缓冲区大小有所改变;0: 退出程序。 "< fout<<"**************************************************"< fout<<"请选择您的操作: "; fout< switch(i) { case0: cout<<"成功退出程序! "< fout<<"成功退出程序! "< break; case1: producer(s); if(s->geta()==0) fout<<"成功生产出一件产品! "< else { fout<<"操作失败,临界区已满! "< s->deca(); } break; case2: consumer(s); if(s->getb()==0) fout<<"成功消费一件产品! "< else { fout<<"操作失败,临界区为空! "< s->decb(); } break; case3: showbuf(s); fout<<"临界区已占用"< break; case4: deletes; cout< cout<<"另一种不同产品的缓冲区的大小为: "< cin>>n; fout< fout<<"另一种不同产品的缓冲区的大小为: "< fout< s=newSeqSquare(n); break; default: cout<<"请输入正确的菜单项进行操作! "< fout<<"请输入正确的菜单项进行操作! "< } } } 3.4自我评价与总结 在这次课设中为模拟进程同步我采用了C++来完成。 在程序中采用了C++语言中类以及数组的运用,我对数组的操作是按照“先进先出”的方法进行运作的,这是参考了栈的工作原理,因为缓冲区一般也是堆栈,比较符合设计要求。 此外,还有一点就是我运用了文件输出流方法(main(): ofstreamfout;fout.open("processing.txt");)对操作过程进行记录。 这次课设中也存在很多的不足和缺点,最明显的是模拟进程同步的过程我感觉做的很粗糙,自己所想的模拟过程的确得到实现了,但是感觉灵活性不太高,思考还不过全面,应该以后多注意一下,多考虑考虑才是。 为完成这次课设中的功能,我重新将《C++程序设计教程》和《数据结构》的几个重要章节复习了一遍,对类、数组、C++的I/O流类库以及堆栈的语句格式、注意细节都再一次熟悉,尤其其实对类和文件输出流之间的磨合,在类中的输出语句cout,如何转换到在主函数中用fout输出到文件中。 不过,在编程过程中还是出现很多的问题,最终在同学的帮助下顺利调试成功。 通过这次课设我发现自己对C++强大丰富的语句方法用得太呆板,不够灵活,总是想到那些常用的,而忽略了颗粒让语句更简短的方法,以后要多多注意才是。 在完成后我发现如果采用Java高级语言来做,可以用事件监听类的方法完成生产者和消费者之间的同步问题。 本次课设让我学到了很多,对操作系统老师所教授的信号量机制解决进程互斥和同步问题都得到了训练,同时也让我温习以前所学习的高级语言。 4.参考文献 < <<计算机操作系统教程>>清华大学出版社,2006 <
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 进程 同步 模拟 设计