首页 > 代码库 > 跟我一起做面试题-linux线程编程(5)

跟我一起做面试题-linux线程编程(5)

如题所述:

生产者消费者问题

这是一个非常经典的多线程题目,题目大意如下:有一个生产者在生产产品,这些产品将提供给若 干个消费者去消费,为了使生产者和消费者能并发执行,在两者之间设置一个有多个缓冲区的缓冲池,生产者将它生产的产品放入一个缓冲区中,消费者可以从缓冲 区中取走产品进行消费,所有生产者和消费者都是异步方式运行的,但它们必须保持同步,即不允许消费者到一个空的缓冲区中取产品,也不允许生产者向一个已经 装满产品且尚未被取走的缓冲区中投放产品。

 

  1 #include <stdio.h>  2 #include <stdlib.h>  3 #include <string.h>  4 #include <pthread.h>  5 #include <errno.h>  6 #include <stdarg.h>  7 #include <unistd.h>  8 #include <limits.h>  9 #include <sys/ipc.h> 10 #include <sys/msg.h> 11 #include <sys/types.h>   12 #include <sys/time.h> 13 #include <signal.h> 14   15   16 #define FULL    5           // 仓库满状态,抢iphone哟,这么少 17 #define EMPTY   0           //  仓库空状态 18 #define INIT_DEPOT_NUM  2   // 初始仓库状态 19 #define CONSUMER_NUM 9     //  消费者数量  20 #define PRODUCER_NUM 1      // 生产者数量 21 #define RUN     0           //  系统运行状态 22 #define OVER    1           // 系统关闭状态 23  24 int product;                //  具体仓库里的产品 25 int shutdown; 26 pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER; 27 pthread_cond_t  product_cond = PTHREAD_COND_INITIALIZER; 28 pthread_cond_t  consume_cond = PTHREAD_COND_INITIALIZER; 29  30  31 #define myprintf( ... )  32     do{  33     mprintf(__FILE__, __FUNCTION__, __LINE__,##__VA_ARGS__);  34     }while(0) 35  36  37  38  39 int mprintf(const char *file_name, const char *func_name, int line, const char *fmt, ...) 40 { 41     va_list     strArgPtr; 42     int la,lb; 43     la = fprintf(stdout, "[%-15s]-[%-10s]-[%04d]", file_name, func_name, line); 44     va_start(strArgPtr, fmt); 45     lb = vfprintf(stdout, fmt, strArgPtr); 46     va_end(strArgPtr); 47     printf("\n"); 48     fflush(stdout); 49     return (la+lb); 50 } 51  52 void * fun_producer(void *arg) 53 { 54     int i; 55     int name = (int)arg; 56     for(;;) 57     { 58             if( pthread_mutex_lock(&mylock)) 59             { 60                 myprintf("pthread_mutex_lock error errmsg[%s]\n", strerror(errno)); 61                 exit(0); 62             } 63             while(1) 64             { 65                 if(shutdown == OVER) 66                 { 67                     myprintf("producer id [%d] go home now", name); 68                     if(pthread_mutex_unlock(&mylock)) 69                     { 70                         myprintf("pthread_mutex_unlock error errmsg[%s]\n", strerror(errno)); 71                         exit(0); 72                     } 73                     pthread_exit(NULL);     74                 } 75                 if ( product >= FULL) 76                 { 77                      myprintf("producer id [%d] prompt depot full [%d]",name, product); 78                      break; 79                 } 80                 else 81                 { 82                     product++; 83                     myprintf("producer id [%d] put product [%d] into depot",name, product); 84                     break; 85                 } 86                          87                 if(pthread_cond_wait(&product_cond, &mylock)) 88                 { 89                     myprintf("wait error errmsg[%s]\n", strerror(errno)); 90                     exit(0); 91                 } 92             } 93             if(pthread_mutex_unlock(&mylock)) 94             { 95                 myprintf("pthread_mutex_unlock error errmsg[%s]\n", strerror(errno)); 96                 exit(0); 97             } 98             if(pthread_cond_broadcast(&consume_cond)) 99             {100                 myprintf("pthread_cond_broadcast error errmsg[%s]\n", strerror(errno));101                 exit(0);102             }103             //sleep(1);104     }105 }106 107 void * fun_consumer(void *arg)108 {109     int i;110     int name = (int)arg;111     for(;;)112     {113             if( pthread_mutex_lock(&mylock))114             {115                 myprintf("pthread_mutex_lock error errmsg[%s]\n", strerror(errno));116                 exit(0);117             }118             while(1)119             {120                 if(shutdown == OVER)121                 {122                     myprintf("consumer id [%d] go home now", name);123                     if(pthread_mutex_unlock(&mylock))124                     {125                         myprintf("pthread_mutex_unlock error errmsg[%s]\n", strerror(errno));126                         exit(0);127                     }128                     pthread_exit(NULL);    129                 }130                 if ( product > EMPTY)131                 {132                      myprintf("consumer id [%d] take product from depot [%d]", name, product);133                      product--;134                      break;135                 }      136                 if(pthread_cond_wait(&consume_cond, &mylock))137                 {138                     myprintf("wait error errmsg[%s]\n", strerror(errno));139                     exit(0);140                 }141             }142             if(pthread_mutex_unlock(&mylock))143             {144                 myprintf("pthread_mutex_unlock error errmsg[%s]\n", strerror(errno));145                 exit(0);146             }147             if(pthread_cond_broadcast(&product_cond))148             {149                 myprintf("pthread_cond_broadcast error errmsg[%s]\n", strerror(errno));150                 exit(0);151             }152             //sleep(1);153     }154 }155 156 void allover(int sig)157 {158         if( pthread_mutex_lock(&mylock))159         {160             myprintf("pthread_mutex_lock error errmsg[%s]\n", strerror(errno));161             exit(0);162         }163         shutdown = OVER;164         if( pthread_mutex_unlock(&mylock))165         {166             myprintf("pthread_mutex_lock error errmsg[%s]\n", strerror(errno));167             exit(0);168         }169         if(pthread_cond_broadcast(&consume_cond))170         {171             myprintf("pthread_cond_broadcast error errmsg[%s]\n", strerror(errno));172             exit(0);173         }174         if(pthread_cond_broadcast(&product_cond))175         {176             myprintf("pthread_cond_broadcast error errmsg[%s]\n", strerror(errno));177             exit(0);178         }179 }180 181 182 int appInit()183 {184     shutdown = RUN;185     int i;186     product = INIT_DEPOT_NUM;187     if ( signal(SIGUSR1, allover)== SIG_ERR)188     {189         myprintf("signal  failure");    190         return -1;    191     }192     if ( signal(SIGTERM, allover)== SIG_ERR)193     {194         myprintf("signal  failure");    195         return -1;    196     }197     if ( signal(SIGINT, allover)== SIG_ERR)198     {199         myprintf("signal  failure");    200         return -1;    201     }202     if ( signal(SIGQUIT, allover)== SIG_ERR)203     {204         myprintf("signal  failure");    205         return -1;    206     }207 //    pthread_mutex_init(&mylock, NULL);208 //    pthread_cond_init(&cond, NULL);209     return 0; 210 }211 212 int appDone()213 {214     int i;215 //    pthread_cond_destroy(&cond);216 //    pthread_mutex_destroy(&mylock);217     return 0;218 }219 220 int main(int argc, char *argv[])221 {222  223     pthread_t consumer[CONSUMER_NUM];224     pthread_t producer[PRODUCER_NUM];225 226     int ret;227     int i;228     ret = appInit();229     if(ret)230     {231         myprintf("appinit failure");232         return -1;    233     }234     235     for( i = 0; i < CONSUMER_NUM; i++)236     {237         ret = pthread_create(&consumer[i], NULL, fun_consumer, (void*)i);238         if(ret)239         {240             myprintf("pthread_create ta error [%s]", strerror(errno));241             return 1;242         }        243     }244     245     for( i = 0; i < PRODUCER_NUM; i++)246     {247         ret = pthread_create(&producer[i], NULL, fun_producer, (void*)i);248         if(ret)249         {250             myprintf("pthread_create ta error [%s]", strerror(errno));251             return 1;252         }         253     }254     for( i = 0; i < CONSUMER_NUM; i++)255         pthread_join(consumer[i], NULL);256     for( i = 0; i < PRODUCER_NUM; i++)257         pthread_join(producer[i], NULL);258 259     myprintf("main thread exit");260     ret = appDone();261     if(ret)262     {263         myprintf("appDone failure");264         return -1;    265     }266     return 0;267 }
View Code

代码一般在以前的基础上更改,有些bug的修复并不会同步到之前的版本。以最新版本为要。

本版本增加一个控制,对一些常用信号给出响应,并结束程序。



 

跟我一起做面试题-linux线程编程(5)