利用条件变量实现多线程生产者消费者问题

以下程序实现linux多线程下一个生产者多个消费者的问题。

 

  
  
  
  
  1. /* 
  2. 使用条件变量时,线程在不满足条件时会被挂起。 
  3. 在消费品都消费完毕,生产者线程停止生产后, 
  4. 消费者线程因为缓冲区内容为空,将一直挂起。 
  5. 需设置一个全局变量start,当生产者已经停止时,需告知其他消费者解除挂起的状态。 
  6. */ 
  7.  
  8. #include <stdio.h>   
  9. #include <stdlib.h>   
  10. #include <string.h>   
  11. #include <pthread.h>   
  12. #define NUMS 10000  //表示生产,消费的次数   
  13. #define CAPACITY 50 //定义缓冲区最大值   
  14. int capacity = 0; //当前缓冲区的产品个数   
  15. pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;//互斥量   
  16. pthread_cond_t mycond = PTHREAD_COND_INITIALIZER;//条件变量   
  17.  
  18. int start = 0; 
  19.    
  20. void *produce(void *args)   
  21. {   
  22.     int i = 0;   
  23.     for (; i < NUMS; )   
  24.     {   
  25.         pthread_mutex_lock(&mylock);//加锁   
  26.         if (capacity >= CAPACITY) //当前产品个数大于等于缓冲区最大值,则不把产品放入缓冲区。   
  27.         {   
  28.             printf("缓冲区已满,无法放入产品\n");   
  29.             pthread_cond_wait(&mycond, &mylock); 
  30.         } else {//将产品放入缓冲区   
  31.             ++capacity;   
  32.             printf("生产者存入一个产品, 缓冲区大小为:%d\n", capacity);   
  33.             i++;   
  34.         }   
  35.         pthread_mutex_unlock(&mylock);   
  36.         pthread_cond_broadcast(&mycond); 
  37.     }   
  38.      
  39.     pthread_mutex_lock(&mylock);//加锁   
  40.     printf("生产者finish!!!!\n");   
  41.     start = 1; 
  42.     pthread_mutex_unlock(&mylock);  
  43.     pthread_cond_broadcast(&mycond); 
  44.  
  45.     return ((void *) 0);   
  46. }   
  47.    
  48. void * consume(void *args)   
  49. {   
  50.     int i = 0;   
  51.     char *p = (char*)args; 
  52.      
  53.     printf("消费者%s start!!!!!!!!!\n", p);   
  54.     for (; i < NUMS; )   
  55.     {   
  56.         pthread_mutex_lock(&mylock);   
  57.         if (capacity > 0)    
  58.         {   
  59.             --capacity;   
  60.             printf("消费者%s消耗一个产品,缓冲区大小为:%d\n", p, capacity);   
  61.             i++;   
  62.         }  
  63.         else if(capacity <= 0 && start != 1)         
  64.         { //当没获取到资源时,将被wait挂起。当其他线程退出后,将不会有broadcast对wait进行解除。 
  65.           //这将导致循环未结束的线程挂起。所以需引入下一个分支的判断 
  66.   
  67.             printf("%s 缓冲区已空,无法消耗产品\n", p);   
  68.             pthread_cond_wait(&mycond, &mylock); 
  69.               
  70.         }  
  71.         else if(capacity <= 0 && start == 1)  
  72.         {//start为1,说明生产者进程已经停止,所以应该释放锁,同时,跳出循环,结束线程。 
  73.             pthread_mutex_unlock(&mylock);   
  74.             //pthread_cond_broadcast(&mycond);//可以不加??? 
  75.             break
  76.         } 
  77.  
  78.         pthread_mutex_unlock(&mylock);   
  79.         pthread_cond_broadcast(&mycond); 
  80.     }   
  81.  
  82.     pthread_mutex_lock(&mylock);   
  83.     printf("消费者%s finish!!!!!!!!!\n", p);   
  84.     pthread_cond_broadcast(&mycond); 
  85.  
  86.     pthread_mutex_unlock(&mylock);   
  87.     return ((void *) 0);   
  88. }   
  89.    
  90. #define CNUM 5 
  91.  
  92. int main(int argc, char** argv) {   
  93.    
  94.     int err;   
  95.     pthread_t produce_tid;   
  96.     pthread_t consume_tid[CNUM];   
  97.     void *ret;   
  98.     err = pthread_create(&produce_tid, NULL, produce, NULL);//创建线程   
  99.     if (err != 0)    
  100.     {   
  101.         printf("线程producer创建失败:%s\n", strerror(err));   
  102.         exit(-1);   
  103.     }   
  104.  
  105.     int i = 0; 
  106.     char *pfree[CNUM] = {0}; 
  107.  
  108.     for(i= 0; i < CNUM; i++) 
  109.     { 
  110.         char* pc = NULL; 
  111.         pc = (char*)malloc(sizeof(char) * (strlen("consumer") + 2)); 
  112.         sprintf(pc, "consumer%d", i); 
  113.         pfree[i] = pc; 
  114.  
  115.         err = pthread_create(consume_tid + i, NULL, consume, (void*)pc);   
  116.         if (err != 0)   
  117.         {   
  118.             printf("线程consumer创建失败:%s\n", strerror(err));   
  119.             continue
  120.             //exit(-1);   
  121.         }   
  122.     } 
  123.  
  124.     err = pthread_join(produce_tid, &ret);//主线程等到子线程退出   
  125.     if (err != 0)    
  126.     {   
  127.         printf("生产着线程分解失败:%s\n", strerror(err));   
  128.         exit(-1);   
  129.     }   
  130.  
  131.     for(i= 0; i < CNUM; i++) 
  132.     { 
  133.         free(pfree[i]); 
  134.         err = pthread_join(consume_tid[i], NULL);   
  135.         if (err != 0)   
  136.         {   
  137.             printf("消费者线程分解失败:%s\n", strerror(err));   
  138.             continue;   
  139.         }   
  140.     } 
  141.     return (EXIT_SUCCESS);   
  142. }   

 

你可能感兴趣的:(条件变量,linux多线程)