码迷,mamicode.com
首页 > 其他好文 > 详细

生产者消费者之信号量的使用

时间:2015-05-07 11:54:50      阅读:253      评论:0      收藏:0      [点我收藏+]

标签:

实验报告

一、实验目的

1.熟悉临界资源、信号量及PV操作的定义与物理意义

2.了解进程通信的方法

3.掌握进程互斥与同步的相关知识

4.掌握用信号量机制解决进程之间的同步与互斥问题

5.实现生产者-消费者问题,深刻理解进程同步问题

 

二、实验环境

Linux系统

 

三、实验内容

在Linux操作系统下用C或C++实现经典同步问题:生产者-消费者问题,具体要求如下:

1. 一个大小为10的缓冲区,初始状态为空。

2. 2个生产者,随机等待一段时间,往缓冲区中添加数据,若缓冲区已满,等待消费者取走数据之后再添加,重复10次。

3. 2个消费者,随机等待一段时间,从缓冲区中读取数据,若缓冲区为空,等待生产者添加数据之后再读取,重复10次。

 

四、程序实现

1.程序中使用的数据结构及说明

1.1缓冲区

缓冲区采用循环队列表示,利用头、尾指针来存放、读取数据,以及判断队列是否为空。缓冲区中数组大小为10。

#define BUFFERNUM 10 

//缓冲区队列

struct Buffer_Queue {

     char production[BUFFERNUM];  //产品

     int front, rear;             //头指针和尾指针

     int num;                     //缓冲区里面字母数量      

};

 

1.2信号量

相关信号量的定义采用semaphore.h里面附带的结构

/*信号量*/

//空的信号量和满的信号量

sem_t empty_sem, full_sem;  

//静态创建条件变量

pthread_cond_t full = PTHREAD_COND_INITIALIZER;        //满的变量

pthread_cond_t empty = PTHREAD_COND_INITIALIZER;       //空的变量

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;      //互斥锁

 

2.核心算法

2.1生产者

void *producer(void *arg)

{

     struct Buffer_Queue *q;

     q = (struct Buffer_Queue *) arg;

     while(1)

     {

         pthread_mutex_lock(&lock);      

         while (q->num == BUFFERNUM)    //缓冲区已经满了,等待

         {           

              pthread_cond_wait(&full, &lock);

         }

         sem_wait(&empty_sem);

 

         /*生产产品*/

         char c = getRandChar();                                      //随机获取字母

         q->rear = (q->rear + 1) % BUFFERNUM;                         //计算新的尾指针 

         q->production[q->rear] = c;                                  //写入新产品

         q->num++;

        

         sem_post(&full_sem);

         if (q->num == 1) {

              pthread_cond_signal(&empty);   

         }

         pthread_mutex_unlock(&lock);

 

         sleep(rand() % 2);            

     }

}

2.2消费者

void *consumer(void *arg)

{

     struct Buffer_Queue *q;

     q = (struct Buffer_Queue *) arg;

     while(1)

     {

         pthread_mutex_lock(&lock);       

         while (q->num == 0)           //缓冲区已经空了,等待

         {       

              pthread_cond_wait(&empty, &lock);

         }

         sem_wait(&full_sem);

 

         /*消费产品*/

         q->front = (q->front + 1) % BUFFERNUM;    //计算新的头指针

         char c = q->production[q->front];         //消费产品

         q->production[q->front] = ‘ ‘;            //

         q->num--;

 

         sem_post(&empty_sem);

         if (q->num == BUFFERNUM - 1) {

              pthread_cond_signal(&full);

         }

         pthread_mutex_unlock(&lock);

         sleep(rand() % 2);

     }

}

 

3.源程序及注释

#include <pthread.h>

#include <stdio.h>

#include <semaphore.h>

#include <time.h>

 

/*信号量*/

//空的信号量和满的信号量

sem_t empty_sem, full_sem;  

//静态创建条件变量

pthread_cond_t full = PTHREAD_COND_INITIALIZER;        //满的变量

pthread_cond_t empty = PTHREAD_COND_INITIALIZER;       //空的变量

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;      //互斥锁

 

#define BUFFERNUM 10   

 

//缓冲区队列

struct Buffer_Queue {

       char production[BUFFERNUM];  //产品

       int front, rear;             //头指针和尾指针

       int num;                     //缓冲区里面字母数量       

};

 

//输出设计者信息

void printDesign()

{

       printf("   ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓\n");

       printf("   ┃         生产者-消费者问题实现    ┃\n");

       printf("   ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫\n");

}

 

//随机产生生产字符

char getRandChar()

{

       int temp = rand()%26;

       return (‘a‘+temp);

}

 

//打印进程运行结果

void printTime()

{

       //打印时间

       time_t now;

       struct tm *timenow;         //实例化tm结构指针

       time(&now);

       timenow = localtime(&now);

       printf("执行时间: %s ",asctime(timenow));

}

 

//生产者1

void *producer1(void *arg)

{

       struct Buffer_Queue *q;

       q = (struct Buffer_Queue *) arg;

       while(1)

       {

              pthread_mutex_lock(&lock);      

              while (q->num == BUFFERNUM)    //缓冲区已经满了,等待

              {           

                     pthread_cond_wait(&full, &lock);

              }

              sem_wait(&empty_sem);

 

              /*生产产品*/

              char c = getRandChar();                                      //随机获取字母

              q->rear = (q->rear + 1) % BUFFERNUM;                         //计算新的尾指针  

              q->production[q->rear] = c;                                  //写入新产品

              q->num++;

             

              /*打印输出结果*/

              printf("-------------------------------------------------------------\n");

              printTime();              //程序运行时间

              int i;

              printf("缓冲区数据(%d个):",q->num);                  //打印缓冲区中的数据

              if(q->front < q->rear)

              {

                     for(i = q->front; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              else

              {

                     for(i = q->front; i < BUFFERNUM; i++)

                            printf("%c ",q->production[i]);

                     for(i = 0; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              printf("\n当前执行的进程:生产者1\n");   //打印当前执行的进程

              printf("产生的数据:%c\n",c);      //打印产生或消费的数据

              printf("-------------------------------------------------------------\n");

 

              sem_post(&full_sem);

 

              if (q->num == 1) {

                     pthread_cond_signal(&empty);   

              }

              pthread_mutex_unlock(&lock);

 

              sleep(rand() % 2);           

       }

}

 

//生产者2

void *producer2(void *arg)

{

       struct Buffer_Queue *q;

       q = (struct Buffer_Queue *) arg;

       while(1)

       {

              pthread_mutex_lock(&lock);      

              while (q->num == BUFFERNUM)    //缓冲区已经满了,等待

              {           

                     pthread_cond_wait(&full, &lock);

              }

              sem_wait(&empty_sem);

 

              /*生产产品*/

              char c = getRandChar();                                      //随机获取字母

              q->rear = (q->rear + 1) % BUFFERNUM;                         //计算新的尾指针  

              q->production[q->rear] = c;                                  //写入新产品 

              q->num++;

 

              /*打印输出结果*/

              printf("-------------------------------------------------------------\n");

              printTime();              //程序运行时间

              int i;

              printf("缓冲区数据(%d个):",q->num);                   //打印缓冲区中的数据

              if(q->front < q->rear)

              {

                     for(i = q->front; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              else

              {

                     for(i = q->front; i < BUFFERNUM; i++)

                            printf("%c ",q->production[i]);

                     for(i = 0; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              printf("\n当前执行的进程:生产者2\n");   //打印当前执行的进程

              printf("产生的数据:%c\n",c);      //打印产生或消费的数据

              printf("-------------------------------------------------------------\n");

 

              sem_post(&full_sem);

 

              if (q->num == 1) {

                     pthread_cond_signal(&empty);   

              }

              pthread_mutex_unlock(&lock);

 

              sleep(rand() % 2);           

       }

}

 

//消费者1

void *consumer1(void *arg)

{

       struct Buffer_Queue *q;

       q = (struct Buffer_Queue *) arg;

       while(1)

       {

              pthread_mutex_lock(&lock);       

              while (q->num == 0)           //缓冲区已经空了,等待

              {       

                     pthread_cond_wait(&empty, &lock);

              }

              sem_wait(&full_sem);

 

              /*消费产品*/

              q->front = (q->front + 1) % BUFFERNUM;    //计算新的头指针

              char c = q->production[q->front];         //消费产品

              q->production[q->front] = ‘ ‘;            //

              q->num--;

 

              /*打印输出结果*/

              printf("-------------------------------------------------------------\n");

              printTime();              //程序运行时间

              int i;

              printf("缓冲区数据(%d个):",q->num);                   //打印缓冲区中的数据

              if(q->front < q->rear)

              {

                     for(i = q->front; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              else

              {

                     for(i = q->front; i < BUFFERNUM; i++)

                            printf("%c ",q->production[i]);

                     for(i = 0; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              printf("\n当前执行的进程:消费者1\n");   //打印当前执行的进程

              printf("消耗的数据:%c\n",c);      //打印产生或消费的数据

              printf("-------------------------------------------------------------\n");

 

 

              sem_post(&empty_sem);

              if (q->num == BUFFERNUM - 1) {

                     pthread_cond_signal(&full);

              }

              pthread_mutex_unlock(&lock);

              sleep(rand() % 2);

       }

}

 

//消费者2

void *consumer2(void *arg)

{

       struct Buffer_Queue *q;

       q = (struct Buffer_Queue *) arg;

       while(1)

       {

              pthread_mutex_lock(&lock);       

              while (q->num == 0)           //缓冲区已经空了,等待

              {       

                     pthread_cond_wait(&empty, &lock);

              }

              sem_wait(&full_sem);

 

              /*消费产品*/

              q->front = (q->front + 1) % BUFFERNUM;    //计算新的头指针

              char c = q->production[q->front];         //消费产品

              q->production[q->front] = ‘ ‘;            //

              q->num--;

 

              /*打印输出结果*/

              printf("-------------------------------------------------------------\n");

              printTime();              //程序运行时间

              int i;

              printf("缓冲区数据(%d个):",q->num);                   //打印缓冲区中的数据

              if(q->front < q->rear)

              {

                     for(i = q->front; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              else

              {

                     for(i = q->front; i < BUFFERNUM; i++)

                            printf("%c ",q->production[i]);

                     for(i = 0; i <= q->rear; i++)

                            printf("%c ",q->production[i]);

              }

              printf("\n当前执行的进程:消费者1\n");   //打印当前执行的进程

              printf("消耗的数据:%c\n",c);      //打印产生或消费的数据

              printf("-------------------------------------------------------------\n");

 

 

              sem_post(&empty_sem);

              if (q->num == BUFFERNUM - 1) {

                     pthread_cond_signal(&full);

              }

              pthread_mutex_unlock(&lock);

              sleep(rand() % 2);

       }

}

 

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

{

    //输出设计者

       printDesign();

 

       /*创建缓冲区*/

       //定义

       struct Buffer_Queue *q;

       q = (struct Buffer_Queue *) malloc(sizeof(struct Buffer_Queue));

       //初始化队列

       q->front = q->rear = BUFFERNUM - 1;

       q->num = 0;

 

       /*执行进程*/

       //定义四个线程

       pthread_t pid1, cid1, pid2, cid2;

       //初始化信号量

       sem_init(&empty_sem, 0, BUFFERNUM);  

       sem_init(&full_sem, 0, 0);  

       //创建线程

       pthread_create(&pid1, NULL, producer1, (void *) q);

       pthread_create(&cid1, NULL, consumer1, (void *) q);

       pthread_create(&pid2, NULL, producer2, (void *) q);

       pthread_create(&cid2, NULL, consumer2, (void *) q);

       //销毁线程

       pthread_join(pid1, NULL);

       pthread_join(cid1, NULL);

       pthread_join(pid2, NULL);

       pthread_join(cid2, NULL);

       //销毁信号量

       sem_destroy(&empty_sem);

       sem_destroy(&full_sem);

 

       return 0;

}

 

五、运行结果

1.linux环境下,用gcc编译

1.1编译

 

1.2执行结果

截图1

 

 

 

 

 

截图2

 

 

截图3

 

生产者消费者之信号量的使用

标签:

原文地址:http://www.cnblogs.com/txf1949/p/4484114.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!