zoukankan      html  css  js  c++  java
  • linux下生产者与消费者C实现

    最近做毕设涉及到了生产者与消费者模型,这个东东只在操作系统课程上有点印象,于是花了点时间看了下《unix环境高级编程 》的线程部分,在此记录一下。

    1.多线程的概念就不多说了,pthread.h头文件中包含的几个基本概念及函数:

    • pthread_t————线程ID数据类型,线程ID只在它所属的进程环境中有效;
    • int pthread_create(pthread_t *tidp, const pthread_attr_t *attr, func(void), arg)————创建新的线程,若成功返回0设置tidp指向的单元为新线程的线程IDattr用来设置线程属性,一般默认为NULLfunc为新线程调用的入口函数,该函数只能有一个无类型指针参数arg,若要向函数传递多个参数,需要将所有参数放到一个结构中,再把结构地址传递给arg
    • pthread_t pthread_self(void)————获取自身线程ID
    • void pthread_exit(void *rval_ptr)———终止本线程,用rval_ptr指向的值作为退出码
    • int pthread_join(pthread_t thread, void **rval_ptr)————调用该函数的线程将阻塞,直到thread线程调用pthread_exit、从启动例程返回或被取消,rval_ptr将包含返回码
    • int pthread_cancel(pthread_t tid)————该函数用来请求取消统一进程中的其他线程

     

    2.线程同步————互斥量、读写锁,条件变量

        ​读写锁即共享——独占锁,适合于读的次数远大于写的情况,比较好理解,就不多说了。

      条件变量由互斥量保护,线程在改变条件状态之前必须先锁定互斥量。

        ​生产者与消费者模型用到了互斥量和条件变量,对队列进行读写,下面直接上代码:

    • 队列操作(数据结构的内容),采用链式结构:
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdbool.h>
    #include <string.h>
    #include <time.h>
    #include <unistd.h>
    #include <pthread.h>
    
    #define MAXLENGTH 10    //the maxlength of queue
    
    typedef char * datatype;
    typedef struct node {    //define node
        datatype name;
        struct node *next;
    } node;
    typedef struct queue {    //define queue
        node *front, *rear;
        int len;
    } queue;
    
    void queue_init(queue *q)
    {
        q->front = q->rear = NULL;
        q->len = 0;
    }
    
    void  queue_put(queue *q, datatype new_name)  //入队
    {
        node *mynode = (node *)malloc(sizeof(node));
        mynode->name = new_name;
        mynode->next = NULL;
        if (q->rear)
            q->rear->next = mynode;
        q->rear = mynode;
        if (q->front == NULL)
            q->front = mynode;
        q->len++;
    }
    
    datatype queue_get(queue *q)   //出队
    {
        node *mynode;
        datatype myname;
        if (q->front != NULL)
            mynode = q->front;
        myname = mynode->name;
        q->front = q->front->next;
        q->len--;
        free(mynode);
        return myname;
    }
    
    void queue_print(queue *q)  //print queue
    {
        node *tmp = q->front;
        while(tmp != NULL)
        {
            printf("%s ", tmp->name);
            tmp = tmp->next;
        }
        printf("
    ");
    }
    • 生产者与消费者函数:
    /*define mutex and condtion var*/
    pthread_cond_t q_not_full = PTHREAD_COND_INITIALIZER;
    pthread_cond_t q_not_empty = PTHREAD_COND_INITIALIZER;
    pthread_mutex_t qlock = PTHREAD_MUTEX_INITIALIZER;
    
    /*
     * producer function
     */
    void producer(void *q)
    {
    //    printf("start porducer:
    ");
        queue *qt = q;    //传入的队列
        while(1)
        {
            pthread_mutex_lock(&qlock);
    //        printf("producer has locked the qlock
    ");
            while(qt->len >= MAXLENGTH)    //queue is full
            {
    //            printf("producer is going to waiting
    ");
                pthread_cond_wait(&q_not_full, &qlock);
            }
            queue_put(qt, "* ");
    //        printf("after producer: queue's length is %d
    ", qt->len);
            pthread_mutex_unlock(&qlock);
            pthread_cond_signal(&q_not_empty);
    
    //        printf("producer has unlocked the qlock
    ");
    //        sleep(1);
        }
    }
    
    /*
     * consumer function
     */
    void consumer(void *q)
    {
    //    printf("start consumer:
    ");
        queue *qt = q;
        while(1)
        {
            pthread_mutex_lock(&qlock);
    //        printf("consumer has locked the qlock
    ");
            while(qt->len <= 0)    //queue is empty
            {
    //            printf("consumer is going to waiting
    ");
                pthread_cond_wait(&q_not_empty, &qlock);
            }
            datatype back_name = queue_get(qt);
    //        printf("after consumer, queue's length is %d
    ", qt->len);
            pthread_mutex_unlock(&qlock);
            pthread_cond_signal(&q_not_full);
    //        now process the back_name
    //        printf("cousumer has unlocked the qlock
    ");
    //        sleep(1);
        }
    }
    • 主函数(测试):
    //gcc编译时加上-lpthread
    int
    main() { pthread_t tid1, tid2; queue *q=(queue *)malloc(sizeof(queue)); queue_init(q); // queue_put(q, "one"); // queue_put(q, "two"); // queue_put(q, "three"); // queue_get(q); // printf("len = %d ", q->len); // queue_print(q); long stime = clock(); long etime = clock(); pthread_create(&tid1, NULL, (void *)producer, (void *)q); pthread_create(&tid2, NULL, (void *)consumer, (void *)q); while((float)(etime-stime)/CLOCKS_PER_SEC < 0.00001) { etime = clock(); } return 0; }

     参考:《unix环境高级编程》

  • 相关阅读:
    关于字符的C++函数
    VC6 LINK : fatal error LNK1168: cannot open Debug/Test.exe for writing
    1019 数字黑洞 (20)
    1015 德才论 (25)
    1013 数素数 (20)(20 分)
    1003 我要通过!(20)(20 分)
    今日目标
    MySQL单列索引和组合索引的区别
    Struts2中过滤器和拦截器的区别
    SQL 统计 字段 竖向转横向 (行转列)显示
  • 原文地址:https://www.cnblogs.com/lifan/p/3727811.html
Copyright © 2011-2022 走看看