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

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

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

     

  • 相关阅读:
    原型模型
    V模型
    瀑布模型
    微服务的特点 优点 缺点
    ip地址的分类
    DSSA特定领域软件体系结构
    Git操作 :从一个分支cherry-pick多个commit到其他分支
    【原理】从零编写ILI9341驱动全过程(基于Arduino)
    Arduino驱动ILI9341彩屏(一)——颜色问题
    STL库学习笔记(一)——什么是STL?
  • 原文地址:https://www.cnblogs.com/biglucky/p/4647910.html
Copyright © 2020-2023  润新知