进程机制与并发程序设计-Linux下C实现(二) 生产者与消费者问题

          进程机制与并发程序设计-Linux下C实现(二) 生产者与消费者问题
                                                                       作者:刘寅 08-01-06

 

 

一,问题分析:

在学习进程互斥中,有个著名的问题:生产者-消费者问题。这个问题是一个标准的、著名的同时性编程问题的集合:一个有限缓冲区和两类线程,它们是生产者和消费者,生产者把产品放入缓冲区,相反消费者便是从缓冲区中拿走产品。生产者在缓冲区满时必须等待,直到缓冲区有空间才继续生产。消费者在缓冲区空时必须等待,直到缓冲区中有产品才能继续读取。在这个问题上主要考虑的是:缓冲区满或缓冲区空以及竞争条件(race condition)

二,伪码分析:


empty为缓冲区中空元素的个数,初值为n

i

j

3-8 环形缓冲区

flul 为缓冲区中已生产元素的个数, 初值为0

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 循环队列的实现

 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        *= 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 /**/ /*
 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 本项目中用到一些数据结构,详细的请参考代码

Code
 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


 源码下载

转载于:https://www.cnblogs.com/dtdnh520/archive/2008/01/06/1027738.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值