生产者消费者问题--进阶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

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

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

 

你可能感兴趣的:(生产者消费者)