生产者消费者问题--进阶2

基于上一节生产者消费者问题--进阶再结合顺序循环队列来实现生产者消费者问题

主要变化就是把需要操作的资源变成操作循环队列,代码如下:

circularQueue.h

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#define FREE(p) \
    if (p != NULL) {\
        free(p);\
        p = NULL;\
    }

typedef struct{
    //int data[QUEUE_SIZE]; //队列中的元素
    int *data;
    int cqHead;     //指向队首元素
    int cqTail;     //指向队尾元素
    int size;       //当前队列的大小
    int maxSize;    //可以容纳的最大大小
}CIRCULAR_QUEUE, *P_CIRCULAR_QUEUE;

int IsQueEmpty(P_CIRCULAR_QUEUE cQue);
int IsQueFull(P_CIRCULAR_QUEUE cQue);
int getQueueSize(P_CIRCULAR_QUEUE cQue);
int getQueueHead(P_CIRCULAR_QUEUE cQue);
int getQueueHeadData(P_CIRCULAR_QUEUE cQue);
int getQueueTail(P_CIRCULAR_QUEUE cQue);
int getQueueTailData(P_CIRCULAR_QUEUE cQue);

//队列是先进先出FIFO
void InitCircularQue(P_CIRCULAR_QUEUE cQue, int maxsize);
void enterCircularQue(P_CIRCULAR_QUEUE cQue, int elem);
int leaveCircularQue(P_CIRCULAR_QUEUE cQue);
void ShowQue(P_CIRCULAR_QUEUE cQue);
void delQue(P_CIRCULAR_QUEUE cQue);

circularQueue.c

/*初始化:head = tail = 0;
 * 队列空:head == tail;
 * 队列满:(tail + 1) % MaxSize == head;
 * 元素数:num = (tail - head + MaxSize) % MaxSize
 * */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "circularQueue.h"

//判断循环队列是否为空
int IsQueEmpty(P_CIRCULAR_QUEUE cQue)
{
    return cQue->cqHead == cQue->cqTail;
}

//判断循环队列是否满
int IsQueFull(P_CIRCULAR_QUEUE cQue)
{ //为了区分队空的情况和队满的情况,使用+1来空出一个数据
    return (cQue->cqTail + 1) % cQue->maxSize == cQue->cqHead;
}

//获取循环队列的大小
int getQueueSize(P_CIRCULAR_QUEUE cQue)
{
   cQue->size = (cQue->cqTail - cQue->cqHead + cQue->maxSize) % cQue->maxSize;
   printf("cqTail[%d], cqHead[%d], size[%d]\n", cQue->cqTail, cQue->cqHead, cQue->size);
   return cQue->size;
}

//获取循环队列队首的位置
int getQueueHead(P_CIRCULAR_QUEUE cQue)
{
     return cQue->cqHead;
}

//获取循环队列队首元素
int getQueueHeadData(P_CIRCULAR_QUEUE cQue)
{
    return cQue->data[cQue->cqHead];
}

//获取循环队列队尾的位置
int getQueueTail(P_CIRCULAR_QUEUE cQue)
{
     return cQue->cqTail;
}

//获取循环队列队首元素
int getQueueTailData(P_CIRCULAR_QUEUE cQue)
{
    return cQue->data[cQue->cqTail];
}

//初始化循环队列
void InitCircularQue(P_CIRCULAR_QUEUE cQue, int maxsize)
{
    printf("cque size =%zu\n", sizeof(*cQue));
    cQue->data = (int*)malloc(sizeof(int)*maxsize);
    //memset(cQue, 0, sizeof(*cQue));
    cQue->cqTail = 0;
    cQue->cqHead = 0;
    cQue->size = 0;
    cQue->maxSize = maxsize;
    printf("cqHead[%d], cqTail[%d], maxSize[%d]\n", cQue->cqHead, cQue->cqTail, cQue->maxSize);
}

//向循环队列中插入元素
void enterCircularQue(P_CIRCULAR_QUEUE cQue, int elem)
{
    if(IsQueFull(cQue))
    {
        printf("Elem %d can't push to CircularQueue %p (Full)!\n", elem, cQue);
        return;
    }
    //cQue->data[cQue->cqTail] = elem;
    int *p = cQue->data;
    p[cQue->cqTail] = elem;
    cQue->cqTail = (cQue->cqTail + 1)%cQue->maxSize;
    printf("cqTail ==%d \n", cQue->cqTail);
}

//从循环队列中取数据
int leaveCircularQue(P_CIRCULAR_QUEUE cQue)
{
     if(IsQueEmpty(cQue))
     {
         printf("Queue %p is Empty! \n", cQue);
         return -1;
     }

     int elem = cQue->data[cQue->cqHead];
     cQue->cqHead = (cQue->cqHead + 1)%cQue->maxSize;
     printf("cqHead == %d \n", cQue->cqHead);
     return elem;
}

//显示队列中的所有元素
void ShowQue(P_CIRCULAR_QUEUE cQue)
{
     if(IsQueEmpty(cQue))
     {
         printf("Queue %p is Empty! \n", cQue);
         return ;
     }

     printf("CircularQueue Element: ");
     int elemIdx = cQue->cqHead;
     while((elemIdx % cQue->maxSize) != cQue->cqTail)
         printf("%d ", cQue->data[(elemIdx++) % cQue->maxSize]);
     printf("\n");
}

void delQue(P_CIRCULAR_QUEUE cQue)
{
    cQue->cqTail = cQue->cqHead = 0;
    FREE(cQue->data);

}
View Code

main.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include "circularQueue.h"

#define P_COUNT 5   //producer NO.
#define C_COUNT 5   //NO.
#define MAX 50 //缓冲区的的大小

CIRCULAR_QUEUE gcQue;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //锁住缓冲区
/*队列满的时候,阻塞生产这线程,队列空时阻塞消费者线程*/
pthread_cond_t notFull = PTHREAD_COND_INITIALIZER; //
pthread_cond_t notEmpty = PTHREAD_COND_INITIALIZER;

typedef struct{
    char buffer[MAX];
    int count;
}Buffer;

Buffer share = {"", 0};
char ch = 'A';

void *producer(void *arg)
{
    int id = *(int *)arg;
    printf("[%d] Producer : starting \n", id);
    //while(ch != 'K')
    while(1)
    {
        pthread_mutex_lock(&mutex);
        while(IsQueFull(&gcQue)){
            pthread_cond_wait(&notFull, &mutex);
            printf("[%d] producer wating for not full signal\n", id);
        }
        enterCircularQue(&gcQue, 100);
        //printf("[%d] Producer: put [%d] char[%c]\n", id, share.count-1, ch );
        pthread_cond_signal(&notEmpty);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
    sleep(1);
    printf("Produce: Exiting \n");
}

void *consumer(void *junk)
{
    int id = *(int *)junk;
    printf("\t[%d] Consumer : starting\n", id);
    //while (ch != 'K')
    while (1)
    {
        pthread_mutex_lock(&mutex);
        printf("\t [%d] Consumer : Waiting\n", id);
        while(IsQueEmpty(&gcQue)){
            pthread_cond_wait(&notEmpty, &mutex);  //条件不成立释放锁.
            printf("\t[%d] Consumer wating for not empty signal\n", id);
        }
        leaveCircularQue(&gcQue);
        pthread_cond_signal(&notFull);
        pthread_mutex_unlock(&mutex);
        sleep(1);
    }
}

int main()
{
    int i;
    pthread_t t_read[C_COUNT], t_write[P_COUNT];

    InitCircularQue(&gcQue, MAX+1);
    int *pId=(int *)malloc(sizeof(int)*P_COUNT);
    int *cId=(int *)malloc(sizeof(int)*C_COUNT);
    for(i = 0; i < P_COUNT; ++i){
        pId[i] = i;
        pthread_create(&t_write[i], NULL, (void *)producer, (void *)&pId[i]);
    }
    for(i = 0; i < C_COUNT; ++i){
        cId[i] = i;
        pthread_create(&t_read[i], NULL, (void *) consumer, (void *)&cId[i]);
    }

    for(i = 0; i < P_COUNT; ++i){
        pthread_join(t_read[i], NULL);
    }
    for(i = 0; i < C_COUNT; ++i){
        pthread_join(t_write[i], NULL);
    }

    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&notFull);
    pthread_cond_destroy(&notEmpty);
    delQue(&gcQue);
    return 0;
}
View Code

生产者消费者问题也缓冲区无界的情况,一般链表就是实现缓冲区的一种方法,可以根据用链表实现队列的功能

来修改临界区代码,类似上面循环队列. 

 

posted @ 2015-07-15 11:55  Magnum Programm Life  阅读(434)  评论(0编辑  收藏  举报