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("\n"); }
  • 生產者與消費者函數:
/*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:\n");
    queue *qt = q;    //傳入的隊列
    while(1) { pthread_mutex_lock(&qlock); // printf("producer has locked the qlock\n");
        while(qt->len >= MAXLENGTH)    //queue is full
 { // printf("producer is going to waiting\n");
            pthread_cond_wait(&q_not_full, &qlock); } queue_put(qt, "* "); // printf("after producer: queue's length is %d\n", qt->len);
        pthread_mutex_unlock(&qlock); pthread_cond_signal(&q_not_empty); // printf("producer has unlocked the qlock\n"); // sleep(1);
 } } /* * consumer function */
void consumer(void *q) { // printf("start consumer:\n");
    queue *qt = q; while(1) { pthread_mutex_lock(&qlock); // printf("consumer has locked the qlock\n");
        while(qt->len <= 0)    //queue is empty
 { // printf("consumer is going to waiting\n");
            pthread_cond_wait(&q_not_empty, &qlock); } datatype back_name = queue_get(qt); // printf("after consumer, queue's length is %d\n", qt->len);
        pthread_mutex_unlock(&qlock); pthread_cond_signal(&q_not_full); // now process the back_name // printf("cousumer has unlocked the qlock\n"); // 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\n", 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環境高級編程》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM