zoukankan      html  css  js  c++  java
  • 生产者消费者问题--进阶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]
    ", 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
    ", 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]
    ", 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)!
    ", 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 
    ", cQue->cqTail);
    }
    
    //从循环队列中取数据
    int leaveCircularQue(P_CIRCULAR_QUEUE cQue)
    {
         if(IsQueEmpty(cQue))
         {
             printf("Queue %p is Empty! 
    ", cQue);
             return -1;
         }
    
         int elem = cQue->data[cQue->cqHead];
         cQue->cqHead = (cQue->cqHead + 1)%cQue->maxSize;
         printf("cqHead == %d 
    ", cQue->cqHead);
         return elem;
    }
    
    //显示队列中的所有元素
    void ShowQue(P_CIRCULAR_QUEUE cQue)
    {
         if(IsQueEmpty(cQue))
         {
             printf("Queue %p is Empty! 
    ", cQue);
             return ;
         }
    
         printf("CircularQueue Element: ");
         int elemIdx = cQue->cqHead;
         while((elemIdx % cQue->maxSize) != cQue->cqTail)
             printf("%d ", cQue->data[(elemIdx++) % cQue->maxSize]);
         printf("
    ");
    }
    
    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 
    ", 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
    ", id);
            }
            enterCircularQue(&gcQue, 100);
            //printf("[%d] Producer: put [%d] char[%c]
    ", id, share.count-1, ch );
            pthread_cond_signal(&notEmpty);
            pthread_mutex_unlock(&mutex);
            sleep(1);
        }
        sleep(1);
        printf("Produce: Exiting 
    ");
    }
    
    void *consumer(void *junk)
    {
        int id = *(int *)junk;
        printf("	[%d] Consumer : starting
    ", id);
        //while (ch != 'K')
        while (1)
        {
            pthread_mutex_lock(&mutex);
            printf("	 [%d] Consumer : Waiting
    ", id);
            while(IsQueEmpty(&gcQue)){
                pthread_cond_wait(&notEmpty, &mutex);  //条件不成立释放锁.
                printf("	[%d] Consumer wating for not empty signal
    ", 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

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

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

     

  • 相关阅读:
    深入理解计算机系统 第六章 存储器层次结构 第二遍
    深入理解计算机系统 第六章 存储器层次结构
    深入理解计算机系统 第八章 异常控制流 Part2 第二遍
    深入理解计算机系统 第八章 异常控制流 part2
    深入理解计算机系统 第八章 异常控制流 Part1 第二遍
    深入理解计算机系统 第八章 异常控制流 part1
    深入理解计算机系统 第三章 程序的机器级表示 Part2 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part2
    深入理解计算机系统 第三章 程序的机器级表示 Part1 第二遍
    深入理解计算机系统 第三章 程序的机器级表示 part1
  • 原文地址:https://www.cnblogs.com/biglucky/p/4647910.html
Copyright © 2011-2022 走看看