多进程同步方法解决生产者消费者问题Word格式.docx
《多进程同步方法解决生产者消费者问题Word格式.docx》由会员分享,可在线阅读,更多相关《多进程同步方法解决生产者消费者问题Word格式.docx(13页珍藏版)》请在冰豆网上搜索。
用多进程同步方法解决生产者-消费者问题
设计目的:
通过研究Linux的进程机制和信号量实现生产者消费者问题的并发控制.
说明:
有界缓冲区内设有20个存储单元,放入/取出的数据项设定为1-20这20个整型数.
设计要求:
1)每个生产者和消费者对有界缓冲区进行操作后,即时显示有界缓冲区的全部内容,当前指针位置和生产者/消费者线程的标识符.
2)生产者和消费者各有两个以上.
3)多个生产者或多个消费者之间须有共享对缓冲区进行操作的函数代码.
2、程序设计基本思想:
生产者—消费者问题是一种同步问题的抽象描述。
计算机系统中的每个进程都可以消费或生产某类资源。
当系统中某一进程使用某一资源时,可以看作是消耗,且该进程称为消费者。
而当某个进程释放资源时,则它就相当一个生产者。
一个有限空间的共享缓冲区,负责存放货物。
生产者向缓冲区中放物品,缓冲区满则不能放。
消费者从缓冲区中拿物品,缓冲区空则不能拿。
因为有多个缓冲区,所以生产者线程没有必要在生成新的数据之前等待最后一个数据被消费者线程处理完毕。
同样,消费者线程并不一定每次只能处理一个数据。
在多缓冲区机制下,线程之间不必互相等待形成死锁,因而提高了效率。
多个缓冲区就好像使用一条传送带替代托
架,传送带上一次可以放多个产品。
生产者在缓冲区尾加入数据,而消费者则在缓冲区头读取数据。
当缓冲区满的时候,缓冲区就上锁并等待消费者线程读取数据;
每一个生产或消费动作使得传送带向前移动一个单位,因而,消费者线程读取数据的顺序和数据产生顺序是相同的。
可以引入一个count计数器来表示已经被使用的缓冲区数量。
用Producer和Consumer来同步生产者和消费者线程。
每当生产者线程发现缓冲区满(count=BufferSize),它就等待Consumer事件。
同样,当消费者线程发现缓冲区空,它就开始等待Producer。
生产者线程写入一个新的数据之后,就立刻发出Consumer来唤醒正在等待的消费者线程;
消费者线程在读取一个数据之后,就发出Producer来唤醒正在等待的生产者线程。
通过一个有界缓冲区(用数组来实现,类似循环队列)把生产者和消费者联系起来。
假定生产者和消费者的优先级是相同的,只要缓冲区未满,生产者就可以生产产品并将产品送入缓冲区。
类似地,只要缓冲区未空,消费者就可以从缓冲区中去走产品并消费它。
应该禁止生产者向满的缓冲区送入产品,同时也应该禁止消费者从空的缓冲区中取出产品,这一机制有生产者线程和消费者线程之间的互斥关系来实现。
二、图形描述及算法:
m个生产者、k个消费者、共享n个单元缓冲区
基本算法如下:
三、程序流程图:
、生产者流程结构:
消费者流程结构:
四、数据结构及部分函数描述
a)用一个整型数组Buffer_NUM来代表缓冲区。
生产产品及对已有产品消费都需要访问该组缓冲区。
缓冲区的大小和结构体:
structBuffer
{
intproduct[BUFFER_NUM];
钟秀等编著.高等教育出版社,2010年8月出版
[2]数据结构教程.李春葆等编著清华大学出版社.2009年4月
[3]面向对象程序设计与VisualC++教程陈天华编著清华大学出版社.2009年7月
附源代码:
#include<
>
typedefHANDLESemaphore;
//信号量的Windows原型
#defineP(S)WaitForSingleObject(S,INFINITE)//定义Windows下的P操作
#defineV(S)ReleaseSemaphore(S,1,NULL)//定义Windows下的V操作
#definerate1000
#defineCONSUMER_NUM2/*消费者个数*/
#definePRODUCER_NUM3/*生产者个数*/
#defineBUFFER_NUM20/*缓冲区个数*/
char*thing[8]={"
鸡腿堡"
"
薯条"
可乐"
三明治"
面包"
小笼包"
火腿"
"
馒头"
};
//生产和消费的产品名称
{
intproduct[BUFFER_NUM];
//缓冲区
intstart,end;
//两个指针相当于教材中的inout指针
}g_buf;
SemaphoreEmpty,Full,Mutex;
//分别相当于Empty,Full,Mutex三个信号量
/**************消费者线程*****************************/
DWORDWINAPIConsumer(LPVOIDpara)
//i表示第i个消费者
inti=*(int*)para;
//利用para传入当前消费者的编号
intptr;
//待消费的内容的指针
printf("
消费者%1d:
需要资源\n"
i);
intj=0;
while(j++<
4){
//等待产品
P(Full);
//有产品,先锁住缓冲区
P(Mutex);
//记录消费的物品
ptr=;
//再移动缓冲区指针
=+1)%BUFFER_NUM;
//让其他消费者或生产者使用
消费者%01d:
我需要buf[%d]=%s\n"
i,ptr,thing[[ptr]]);
//消费完毕,并释放一个缓冲
我消费完毕%s\n"
i,thing[[ptr]]);
V(Mutex);
V(Empty);
Sleep(rate*rand()%10+110);
}
return0;
/****************生产者线程********************************/
DWORDWINAPIProducer(LPVOIDpara)
inti=*(int*)para-CONSUMER_NUM;
intdata;
//产品
while(j++<
4)
data=rand()%8;
生产者%01d:
生产出:
%s!
\n"
i,thing[data]);
//等待存放空间
P(Empty);
//有地方,先锁住缓冲区
P(Mutex);
//记录消费的物品
//再移动缓冲区指针
=+1)%BUFFER_NUM;
放到缓冲区buf[%d]=%s\n"
i,ptr,thing[data]);
[ptr]=data;
//放好了完毕,释放一个产品
V(Full);
Sleep(rate/2*rand()%10+110);
intmain(intargc,char*argv[])
//线程技术,前面为消费者线程,后面为生产者线程
HANDLEhThread[CONSUMER_NUM+PRODUCER_NUM];
//线程计数
srand(time(NULL));
rand();
DWORDtid;
inti=0;
//初始化信号量
Mutex=CreateSemaphore(NULL,1,1,"
MutexOfConsumerAndProducer"
);
Empty=CreateSemaphore(NULL,BUFFER_NUM,BUFFER_NUM,"
BufferSemaphone"
Full=CreateSemaphore(NULL,0,BUFFER_NUM,"
ProductSemaphone"
if(!
Empty||!
Full||!
Mutex)
CreateSemaphoneError!
return-1;
inttotalThreads=CONSUMER_NUM+PRODUCER_NUM;
//开启消费者线程
先请消费者上席!
for(i=0;
i<
CONSUMER_NUM;
i++)
hThread[i]=CreateThread(NULL,0,Consumer,&
i,0,&
tid);
if(hThread[i])WaitForSingleObject(hThread[i],10);
生产者就位!
for(;
totalThreads;
i++)
hThread[i]=CreateThread(NULL,0,Producer,&
//生产者和消费者的执行
WaitForMultipleObjects(totalThreads,hThread,TRUE,INFINITE);
}