程序设计"/>
进程机制与并发程序设计
进程机制与并发程序设计-Linux下C实现(二) 生产者与消费者问题作者:刘寅 08-01-06
一,问题分析:
在学习进程互斥中,有个著名的问题:生产者-消费者问题。这个问题是一个标准的、著名的同时性编程问题的集合:一个有限缓冲区和两类线程,它们是生产者和消费者,生产者把产品放入缓冲区,相反消费者便是从缓冲区中拿走产品。生产者在缓冲区满时必须等待,直到缓冲区有空间才继续生产。消费者在缓冲区空时必须等待,直到缓冲区中有产品才能继续读取。在这个问题上主要考虑的是:缓冲区满或缓冲区空以及竞争条件(race condition)。
二,伪码分析:
empty为缓冲区中空元素的个数,初值为n
满
|
空
|
i
|
j
|
图3-8 环形缓冲区
|
Mutex为对缓冲区互斥访问加的锁
Main()
{
codebegin
Productor();
Customer();
codeend
}
Productor() while(true)
{
P(empty)
p(mutex)
生产产品;
往Buffer [i]中放产 品;
V(mutex)
V(full)
}
Customer():
While(true)
{
P(full)
P(mutex)
从Buffer[J]取产品;
V(mutex)
V(empty)
消费产品
}
三,linux下实现:
在linux readhat 9.0下测试通过
进入pro_cus 文件夹,然后用shell运行”make ”命令即可
Pro_cus文件说明
--const.h 在本项目中使用到的一些常量的定义
1 #ifndef CONST_H
2 #define CONST_H
3 #define MaxSize 10 // 栈中最多只有十个元素
4 #define TRUE 1
5 #define FALSE 0
6 #define ERROR 0
7 #define OVERFLOW -2
8 #define OK 1
9 #define MAXSIZE 20
10 #define MAXLEN 100 // 字符串的最大长度
11 #endif
12
13
--exp1.c 本项目的主程序
1 #include < stdio.h >
2 #include < stdlib.h >
3 #include < unistd.h >
4 #include < pthread.h >
5 #include < errno.h >
6 #include < sys / ipc.h >
7 #include < semaphore.h >
8 #include < fcntl.h >
9 #include " Queue.h "
10 #include " const.h "
11 #define N 5
12 time_t end_time;
13 sem_t mutex,full,empty;
14 int fd;
15 Queue * qt; /**/ /*缓冲区*/
16 Elemtype p;
17
18 void consumer( void * arg);
19 void productor( void * arg);
20
21 int main( int argc, char * argv[])
22 {
23 pthread_t id1,id2;
24 pthread_t mon_th_id;
25 int ret;
26 end_time = time(NULL)+30;
27 qt = InitQueue();
28 p.lNumber = 1000;
29 ret=sem_init(&mutex,0,1); /**//*初使化互斥信号量为1*/
30 ret=sem_init(&empty,0,N); /**//*初使化empty信号量为N*/
31 ret=sem_init(&full,0,0); /**//*初使化full信号量为0*/
32 if(ret!=0)
33 {
34 perror("sem_init");
35 }
36 ret=pthread_create(&id1,NULL,(void *)productor, NULL); /**//*创建两个线程*/
37 if(ret!=0)
38 perror("pthread cread1");
39 ret=pthread_create(&id2,NULL,(void *)consumer, NULL);
40 if(ret!=0)
41 perror("pthread cread2");
42 pthread_join(id1,NULL);
43 pthread_join(id2,NULL);
44
45 exit(0);
46}
47 /**/ /*生产者线程*/
48 void productor( void * arg)
49 {
50 int i,nwrite;
51 while(time(NULL) < end_time){
52 sem_wait(&empty);// p(empty)
53 sem_wait(&mutex);// p(mutex)
54 if(TRUE==QueueFull(*qt))
55 {
56 //队满
57 printf("Productor:buffer is full ,please try to write later.\n");
58 }
59 else
60 {
61 EnQueue(qt,p);
62 printf("Productor:write [%d] to buffer \n",p.lNumber);
63 p.lNumber++;
64 }
65
66 sem_post(&full);//v(full)
67 sem_post(&mutex);//v(mutex)
68 sleep(1);
69 }
70} // productor
71
72 /**/ /*消费者线程*/
73 void consumer( void * arg)
74 {
75 int nolock=0;
76 int ret,nread;
77 Elemtype p2;
78 while((time(NULL) < end_time)||(FALSE==(QueueEmpty(*qt))))
79 {
80 sem_wait(&full);//p(full)
81 sem_wait(&mutex);//p(mutex)
82 if(TRUE==QueueEmpty(*qt))
83 {
84 //队空
85 printf("Consumer:the buffer is empty,please try to read later.\n");
86 }
87 else
88 {
89 DeQueue(qt,&p2);
90 printf("Consumer:read [%d] from buffer.\n",p2.lNumber);
91 }
92 sem_post(&empty);//v(empty)
93 sem_post(&mutex);//v(mutex)
94 sleep(2);
95 }/**//*end of while((time(NULL) < end_time)||(FALSE==(QueueEmpty(*qt))))*/
96} // consumer
97
98
--Queue.c 循环队列的实现
2队列的基本操作函数
3*/
4 #include " stdio.h "
5 #include " malloc.h "
6 #include " const.h "
7 #include " Queue.h "
8 /**/ /*
9 初使化队列
10*/
11 Queue * InitQueue()
12 {
13 Queue * Q = (Queue *)malloc(sizeof(Queue));
14
15 Q->front = Q->rear = 0;
16 return Q;
17}
18
19 /**/ /*
20 进队
21*/
22 int EnQueue(Queue * Q,Elemtype x)
23 {
24 if((Q->rear + 1)%MaxSize==Q->front)/**//* 队满 */
25 return FALSE;
26 else
27 {
28 Q->q[Q->rear] = x;
29 Q->rear = (Q->rear+1)%MaxSize;
30 return TRUE;
31 }
32}
33
34 /**/ /*
35 出队
36*/
37 int DeQueue(Queue * Q,Elemtype * x)
38 {
39 if(Q->rear==Q->front)/**//*队空*/
40 return FALSE;
41 else
42 {
43 *x = Q->q[Q->front];
44 Q->front = (Q->front+1)%MaxSize;
45 return TRUE;
46 }
47}
48
49 /**/ /*
50 判断队是否为空,空返回0
51 非空返回 1
52*/
53 int QueueEmpty(Queue Q)
54 {
55 if(Q.rear==Q.front)/**//*队空*/
56 return TRUE;
57 else
58 return FALSE;
59}
60
61 /**/ /*
62 返回队例中的最后的一个元素(原队列还要存在)
63*/
64 Elemtype Last(Queue * Q)
65 {
66
67 Elemtype *prElem = NULL;
68 Queue *prTempQueue;
69 /**//*这个临时队列,把原队列放到里面,当取完最后一
70 个元素后,就把这个队列中的元素放回原来的队列*/
71 prTempQueue = InitQueue();
72 while(QueueEmpty(*Q)==1)
73 {
74 DeQueue(Q,prElem);
75 EnQueue(prTempQueue,*prElem);
76 }
77 while(QueueEmpty(*prTempQueue)==1)
78 {
79 DeQueue(prTempQueue,prElem);
80 EnQueue(Q,*prElem);
81 }
82 return *prElem;
83} /**/ /*Last*/
84
85 /**/ /*
86 判断队是否为满,满返回TRUE
87 非满返回FALSE
88*/
89 int QueueFull(Queue Q)
90 {
91 if(((Q.rear+1)%MaxSize)==Q.front)/**//*队空*/
92 return TRUE;
93 else
94 return FALSE;
95}
96
--Queue.h 循环队列的函数说明
2 #define QUEUE_H_LY
3 #include " Typedefine.h "
4 /**/ /*
52007-12-23 10:31:14
6*/
7 /**/ /*
8 初使化队列信息
9*/
10 Queue * InitQueue();
11 /**/ /*
12 进队(因为没有队满的情况,所以没有返回值)
13*/
14
15 int EnQueue(Queue * Q,Elemtype x);
16 /**/ /*
17 出队,x为出队的那个结点的数据域
18 返回:1成功/0失败
19*/
20 int DeQueue(Queue * Q,Elemtype * x);
21 /**/ /*
22 判断队空1(不空)/0(为空)
23*/
24 int QueueEmpty(Queue Q);
25 /**/ /*
26 统计一个栈链中的元素的个数
27*/
28 int QueueCount(Queue * HQ);
29
30 /**/ /*
31 判断队是否为满,满返回TRUE
32 非满返回FALSE
33*/
34 int QueueFull(Queue Q);
35
36 #endif
37
--Typedefine.h 本项目中用到一些数据结构,详细的请参考代码
1#ifndef TYPEDEFINE_H
2#define TYPEDEFINE_H
3#include "const.h"
4
5typedef struct/**//*字符串的类型*/
6{
7 char data[MAXLEN];//数据区
8 int len;//长度,没包括了'\0'的长度,如"abc",长度为3
9}SString;
10
11//typedef int Elemtype;
12typedef struct
13{
14 SString* strName;//名字
15 long lNumber;//号码
16}Elemtype;
17
18/**//*
19本页面主要是对在程序中使用到的类型做定义
20如结点类型,数据类型
21*/
22
23typedef struct node
24{
25 //结点的数据域
26 Elemtype data;
27
28 //结点的指针域,存放下一个结点的地址
29 struct node *next;
30}SNode;
31
32
33
34/**//*队列的基本结构*/
35typedef struct
36{
37 //存放队列元素
38 Elemtype q[MaxSize];
39
40 //头指针
41 int front;
42
43 //尾指针(尾元素的下一个位置)
44 int rear;
45}Queue;
46
47/**//*
48 链队列的结构定义
49typedef struct
50{
51 SNode *front ,*rear;
52
53}LQueue;
54*/
55
56
57/**//*栈的基本类型定义*/
58typedef struct st
59{
60 Elemtype data[MaxSize];
61 int top;
62}Stack;
63
64
65
66typedef int BOOL;
67typedef int Status;
68
69
70
71#endif
72
源码下载
转载于:.html
更多推荐
进程机制与并发程序设计
发布评论