






















进程机制与并发程序设计-Linux下C实现(二) 生产者与消费者问题
作者:刘寅 08-01-06
在学习进程互斥中,有个著名的问题:生产者-消费者问题。这个问题是一个标准的、著名的同时性编程问题的集合:一个有限缓冲区和两类线程,它们是生产者和消费者,生产者把产品放入缓冲区,相反消费者便是从缓冲区中拿走产品。生产者在缓冲区满时必须等待,直到缓冲区有空间才继续生产。消费者在缓冲区空时必须等待,直到缓冲区中有产品才能继续读取。在这个问题上主要考虑的是:缓冲区满或缓冲区空以及竞争条件(race condition)。
empty为缓冲区中空元素的个数,初值为n
flul为缓冲区中已生产元素的个数,初值为0Mutex为对缓冲区互斥访问加的锁
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 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 循环队列的实现
1
/*
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 循环队列的函数说明
1
#ifndef QUEUE_H_LY
2
#define QUEUE_H_LY
3
#include "Typedefine.h"
4
/*
5
2007-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 本项目中用到一些数据结构,详细的请参考代码
Code
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。