生产者-消费者问题

(3)源程序

#include #include #include #include

typedef HANDLE Semaphore; // 信号量的Windows原型

#define P(S) WaitForSingleObject(S,INFINITE) // 定义Windows下的P操作

#define V(S) ReleaseSemaphore(S,1,NULL) // 定义Windows下的V操作 #define rate 1000

#define CONSUMER_NUM 2 /* 消费者个数 */ #define PRODUCER_NUM 3 /* 生产者个数 */ #define BUFFER_NUM 20 /* 缓冲区个数 */

char *thing[8] = {\豆浆\油条\烧饼\牛奶\包子\烧卖\煎蛋\雪碧\生产和消费的产品名称 struct Buffer {

int product[BUFFER_NUM]; // 缓冲区

int start,end; // 两个指针相当于教材中的 in out 指针 }g_buf;

Semaphore Empty,Full,Mutex; //分别相当于Empty, Full, Mutex三个信号量

/************** 消费者线程*****************************/ DWORD WINAPI Consumer(LPVOID para) {

// i表示第i个消费者

int i = *(int *)para; //利用para传入当前消费者的编号 int ptr; // 待消费的内容的指针 printf(\消费者: 需要资源\\n\ int j=0;

while (j++<4){

// 等待产品 P(Full);

// 有产品,先锁住缓冲区 P(Mutex);

// 记录消费的物品 ptr=g_buf.start;

// 再移动缓冲区指针

g_buf.start= (g_buf.start+1)%BUFFER_NUM; //让其他消费者或生产者使用

- 5 -

printf(\消费者d: 我需要buf[%d]=%s\\n\i, ptr, thing[g_buf.product[ptr]]); //消费完毕,并释放一个缓冲

printf(\消费者d: 我消费完毕%s\\n\i,thing[g_buf.product[ptr]]); V(Mutex); V(Empty);

Sleep(rate*rand()+110); }

return 0; }

/**************** 生产者线程********************************/ DWORD WINAPI Producer(LPVOID para) {

int i = *(int *)para - CONSUMER_NUM; int ptr;

int data; //产品 int j=0;

while(j++<4) {

data=rand()%8;

printf(\生产者d: 生产出: %s!\\n\i,thing[data]); //等待存放空间 P(Empty);

//有地方,先锁住缓冲区 P(Mutex);

//记录消费的物品 ptr=g_buf.end;

//再移动缓冲区指针

g_buf.end =(g_buf.end+1)%BUFFER_NUM;

printf(\生产者d: 放到缓冲区 buf[%d]=%s\\n\i,ptr,thing[data]); g_buf.product[ptr]=data;

//放好了完毕,释放一个产品 //让其他消费者或生产者使用 V(Mutex); V(Full);

Sleep(rate/2*rand()+110); }

return 0; }

int main(int argc,char *argv[])

- 6 -

{

//线程技术,前面为消费者线程,后面为生产者线程

HANDLE hThread[CONSUMER_NUM+PRODUCER_NUM]; // 线程计数

srand(time(NULL)); rand();

DWORD tid; int i=0;

//初始化信号量

Mutex=CreateSemaphore(NULL,1,1,\ Empty=CreateSemaphore(NULL, BUFFER_NUM, BUFFER_NUM, \

Full=CreateSemaphore(NULL,0,BUFFER_NUM,\ if(!Empty||!Full||!Mutex) {

printf(\ Semaphone Error!\\n\

return -1; }

int totalThreads=CONSUMER_NUM+PRODUCER_NUM; //开启消费者线程

printf(\先请消费者上席!\\n\ for(i=0;i

hThread[i]=CreateThread(NULL, 0, Consumer, &i,0,&tid); if(hThread[i])WaitForSingleObject(hThread[i],10); }

printf(\生产者就位!\\n\ for(;i

hThread[i]=CreateThread(NULL,0,Producer,&i,0,&tid); if(hThread[i])WaitForSingleObject(hThread[i],10); }

//生产者和消费者的执行

WaitForMultipleObjects(totalThreads,hThread,TRUE,INFINITE); return 0; }

- 7 -

3 结果及分析

- 8 -

4 设计小结

本次课程设计通过模拟计算机操作系统中经典的“生产者—消费者问题”,巩固了我在操作系统原理课上所学的知识,加深了对操作系统中进程同步和互斥等问题,完成了多进程同步方法解决生产者-消费者问题全部过程,结果满足设计要求。

设计过程中遇到不少困难,在反复研究老师的PPT及课本的原理后才逐渐明晰怎样将代码实现,虽然这学期学过Java,但java不是很熟悉,因此还是选择C++语言。以前学习C++没有深入了解到线程这个概念,在学习Java的时候才知道有专门的线程类。所以我在网上也参考了其他人用C++编写尤其是关于多进程程序的设计实现。在代码的实现过程中,我是主要定义了两个函数 DWORD WINAPI Consumer(LPVOID para) 和 DWORD WINAPI Producer(LPVOID para),在这两个函数中实现PV操作。

通过本次设计,我较好地掌握了通过研究Linux 的进程机制和信号量实现生产者消费者问题的并发控制全过程,尤其是对多进程程序设计方法有了更深的理解,开拓了思路,锻炼了实践动手能手。但是我觉得课程设计的时间有点短,中间又夹杂着好几场考试,所以没能做出界面以便于直观的观察出详细过程,只是用代码实现了要描述的功能且达到了要求,所以改进的空间还比较大。

5 参考文献

[1]汤子瀛.《计算机操作系统》(修订版).西安电子科技大学出版社,2001。 [2]计算机操作系统教程.孙钟秀等编著.高等教育出版社,2010年8月出版 [3]数据结构教程.李春葆等编著 清华大学出版社.2009年4月

[4]面向对象程序设计与Visual C++6.0教程 陈天华编著 清华大学出版社.2009年7月

- 9 -

联系客服:779662525#qq.com(#替换为@) 苏ICP备20003344号-4