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