首页 > 代码库 > 跟我一起做面试题-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 }
代码一般在以前的基础上更改,有些bug的修复并不会同步到之前的版本。以最新版本为要。
本版本增加一个控制,对一些常用信号给出响应,并结束程序。
跟我一起做面试题-linux线程编程(5)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。