Linux下多线程模拟生产者/消费者问题
2015-11-07 20:46
429 查看
/*用线程的同步和互斥来实现"生产者-消费者"问题.*/ /* 多生产者多消费者多缓冲区 生产者和消费者不可同时进行 */ #include <stdio.h> #include <stdlib.h> //#include <unistd.h> #include <pthread.h> #include <semaphore.h> #include <time.h> #define M 10 // 缓冲数目 int in = 0; // 生产者放置产品的位置 int out = 0; // 消费者取产品的位置 int buff[M] = {0}; // 缓冲初始化为0,开始时没有产品 int buffer=0; //单缓冲 sem_t empty_sem; // 同步信号量, 当满了时阻止生产者放产品 sem_t full_sem; // 同步信号量, 当没产品时阻止消费者消费 pthread_mutex_t mutex; // 互斥信号量, 一次只有一个线程访问缓冲 int product_id = 0; //生产者id int consumer_id = 0; //消费者id int product_sum=0; int consumer_sum=0; struct timeval start; //记录时间 struct timeval end; unsigned long timer; /* 打印缓冲情况 */ void print() { int i; for(i = 0; i < M; i++) printf("%d ", buff[i]); } /* 生产者方法 (多缓冲)*/ void *product(void * arg) { int id = ++product_id; int t=*(int *)arg; //t生产者生产时间 while(1) { // 用sleep的数量可以调节生产和消费的速度,便于观察 sleep(t); //sleep(1); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); gettimeofday(&end,NULL); //生产开始时间 in = in % M; product_sum++; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus product_%d in %d. buffer: ", timer,id, in+1); //printf("timer = %ld us\n",timer); buff[in] = 1; print(); printf("\t%d\n",product_sum); ++in; pthread_mutex_unlock(&mutex); sem_post(&full_sem); } } /* 生产者方法 (单缓冲)*/ void *product1(void * arg) { int id = ++product_id; int t=*(int *)arg; while(1) { sleep(t); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); gettimeofday(&end,NULL); product_sum++; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ld product_%d is producing.SUM=%d\n",timer,id,product_sum); buffer=1; pthread_mutex_unlock(&mutex); sem_post(&full_sem); } } /* 生产者方法 交换wait(metux) wait(empty)*/ void *product2(void * arg) { int id = ++product_id; int t=*(int *)arg; while(1) { sleep(t); //sleep(1); pthread_mutex_lock(&mutex); sem_wait(&empty_sem); gettimeofday(&end,NULL); in = in % M; product_sum++; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus product_%d in %d. buffer: ", timer,id, in+1); //printf("timer = %ld us\n",timer); buff[in] = 1; print(); printf("\t%d\n",product_sum); ++in; pthread_mutex_unlock(&mutex); sem_post(&full_sem); } } /* 生产者方法 交换signal(metux) signal(empty)*/ void *product3(void * arg) { int id = ++product_id; int t=*(int *)arg; while(1) { sleep(t); //sleep(1); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); gettimeofday(&end,NULL); in = in % M; product_sum++; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus product_%d in %d. buffer: ", timer,id, in+1); //printf("timer = %ld us\n",timer); buff[in] = 1; print(); printf("\t%d\n",product_sum); ++in; sem_post(&full_sem); pthread_mutex_unlock(&mutex); } } /* 生产者方法 生产者消费者同时访问缓冲区*/ void *product4(void * arg) { int id = ++product_id; int t=*(int *)arg; while(1) { sleep(t); //sleep(1); sem_wait(&empty_sem); pthread_mutex_lock(&mutex); gettimeofday(&end,NULL); in = in % M; product_sum++; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus product_%d in %d. buffer: ", timer,id, in+1); //printf("timer = %ld us\n",timer); buff[in] = 1; print(); printf("\t%d\n",product_sum); ++in; sem_post(&full_sem); pthread_mutex_unlock(&mutex); } } /* 消费者方法(多缓冲) */ void *consumer(void * arg) { int id = ++consumer_id; int t=*(int *)arg; while(1) { // 用sleep的数量可以调节生产和消费的速度 sleep(t); sem_wait(&full_sem); pthread_mutex_lock(&mutex); gettimeofday(&end,NULL); //消费生产时间 consumer_sum++; out = out % M; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus consumer_%d in %d. buffer: ", timer,id, out+1); buff[out] = 0; print(); printf("\t%d\n",consumer_sum); ++out; pthread_mutex_unlock(&mutex); sem_post(&empty_sem); } } /* 消费者方法(单缓冲) */ void *consumer1(void *arg) { int id = ++consumer_id; int t=*(int *)arg; while(1) { sleep(t); sem_wait(&full_sem); pthread_mutex_lock(&mutex); gettimeofday(&end,NULL); consumer_sum++; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ld consumer_%d is consumeing.SUM=%d\n",timer,id, consumer_sum); buffer=0; pthread_mutex_unlock(&mutex); sem_post(&empty_sem); } } /* 消费者方法 wait(metux) wait(empty)互换 */ void *consumer2(void * arg) { int id = ++consumer_id; int t=*(int *)arg; while(1) { sleep(t); pthread_mutex_lock(&mutex); sem_wait(&full_sem); gettimeofday(&end,NULL); consumer_sum++; out = out % M; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus consumer_%d in %d. buffer: ", timer,id, out+1); buff[out] = 0; print(); printf("\t%d\n",consumer_sum); ++out; pthread_mutex_unlock(&mutex); sem_post(&empty_sem); } } /* 消费者方法 signal(metux) signal(empty)互换*/ void *consumer3(void * arg) { int id = ++consumer_id; int t=*(int *)arg; while(1) { sleep(t); sem_wait(&full_sem); pthread_mutex_lock(&mutex); gettimeofday(&end,NULL); consumer_sum++; out = out % M; timer = 1000000 * (end.tv_sec-start.tv_sec)+ end.tv_usec-start.tv_usec; printf("time:%ldus consumer_%d in %d. buffer: ", timer,id, out+1); buff[out] = 0; print(); printf("\t%d\n",consumer_sum); ++out; sem_post(&empty_sem); pthread_mutex_unlock(&mutex); } } /*配置生产者消费者参数*/ void config(int *N1,int *N2,int *T1,int *T2) { FILE *fp; if (!(fp=fopen("config.txt","r"))) { printf("Error in open file!\n"); exit(1); } fscanf(fp,"%d %d %d %d",N1,N2,T1,T2); fclose(fp); } /*选择菜单*/ void menu() { printf("------------------------------------------------------------\n"); printf("------1-多生产者多消费者多缓冲\n"); printf("------2-多生产者多消费者单缓冲\n"); printf("------3-单生产者单消费者单缓冲\n"); printf("------4-单生产者单消费者多缓冲\n"); printf("------5-单生产者多消费者多缓冲\n"); printf("------6-单生产者多消费者单缓冲\n"); printf("------7-多生产者单消费者多缓冲\n"); printf("------8-多生产者单消费者单缓冲\n"); printf("------9-生产者 wait(metux) wait(empty)互换\n"); printf("------10-生产者 signal(metux) signal(empty)互换\n"); printf("------11-消费者 wait(metux) wait(empty)互换\n"); printf("------12-消费者 signal(metux) signal(empty)互换\n"); printf("------0-退出\n"); printf("-------------------------------------------------------------\n"); printf("\n"); } /*多缓冲*/ void f1(int N1,int N2,int T1,int T2,void *product,void *consumer) { //N1,N2分别是生产者消费者数目 //T1,T2分别是生产消费时间 pthread_t id1[N1]; pthread_t id2[N2]; int i; int ret1[N1]; int ret2[N2]; // 初始化同步信号量 int ini1 = sem_init(&empty_sem, 0, M); //信号量将被进程内的线程共享 int ini2 = sem_init(&full_sem, 0, 0); if(ini1 && ini2 != 0) { printf("sem init failed \n"); exit(1); } //初始化互斥信号量 int ini3 = pthread_mutex_init(&mutex, NULL); if(ini3 != 0) { printf("mutex init failed \n"); exit(1); } // 创建N1个生产者线程 for(i = 0; i < N1; i++) { ret1[i] = pthread_create(&id1[i], NULL, product,&T1); if(ret1[i] != 0) { printf("product%d creation failed \n", i); exit(1); } } //创建N2个消费者线程 for(i = 0; i < N2; i++) { ret2[i] = pthread_create(&id2[i], NULL, consumer, &T2); if(ret2[i] != 0) { printf("consumer%d creation failed \n", i); exit(1); } } //销毁线程 for(i = 0; i < N1; i++) { pthread_join(id1[i],NULL); } for(i = 0; i < N2; i++) { pthread_join(id2[i],NULL); } exit(0); } /*单缓冲*/ void f2(int N1,int N2,int T1,int T2,void *product,void *consumer) { pthread_t id1[N1]; pthread_t id2[N2]; int i; int ret1[N1]; int ret2[N2]; int ini1 = sem_init(&empty_sem, 0, 1); int ini2 = sem_init(&full_sem, 0, 0); if(ini1 && ini2 != 0) { printf("sem init failed \n"); exit(1); } int ini3 = pthread_mutex_init(&mutex, NULL); if(ini3 != 0) { printf("mutex init failed \n"); exit(1); } for(i = 0; i < N1; i++) { ret1[i] = pthread_create(&id1[i], NULL, product,&T1); if(ret1[i] != 0) { printf("product%d creation failed \n", i); exit(1); } } for(i = 0; i < N2; i++) { ret2[i] = pthread_create(&id2[i], NULL, consumer,&T2); if(ret2[i] != 0) { printf("consumer%d creation failed \n", i); exit(1); } } for(i = 0; i < N1; i++) { pthread_join(id1[i],NULL); } for(i = 0; i < N2; i++) { pthread_join(id2[i],NULL); } exit(0); } int main(int argc,char* argv) { menu(); int c; //选择功能 scanf("%d",&c); int N1,N2,T1,T2; config(&N1,&N2,&T1,&T2); switch(c) { case 1: gettimeofday(&start,NULL); //程序开始时间 f1(N1,N2,T1,T2,product,consumer); break; case 2: gettimeofday(&start,NULL); f2(N1,N2,T1,T2,product1,consumer1); break; case 3: gettimeofday(&start,NULL); f2(1,1,T1,T2,product1,consumer1); break; case 4: gettimeofday(&start,NULL); f1(1,1,T1,T2,product,consumer); break; case 5: gettimeofday(&start,NULL); f1(1,N2,T1,T2,product,consumer); break; case 6: gettimeofday(&start,NULL); f2(1,N2,T1,T2,product1,consumer1); break; case 7: gettimeofday(&start,NULL); f1(N1,1,T1,T2,product,consumer); break; case 8: gettimeofday(&start,NULL); f2(N1,1,T1,T2,product1,consumer1); break; case 9: gettimeofday(&start,NULL); f1(N1,N2,T1,T2,product2,consumer); break; case 10: gettimeofday(&start,NULL); f1(N1,N2,T1,T2,product3,consumer); break; case 11: gettimeofday(&start,NULL); f1(N1,N2,T1,T2,product,consumer2); break; case 12: gettimeofday(&start,NULL); f1(N1,N2,T1,T2,product,consumer3); break; case 0: break; } return 0; }
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- C#实现多线程的同步方法实例分析
- 浅谈chuck-lua中的多线程
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#多线程学习之(六)互斥对象用法实例
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- C#控制台下测试多线程的方法
- Ruby 多线程的潜力和弱点分析
- C#中WPF使用多线程调用窗体组件的方法
- C#如何对多线程、多任务管理(demo)
- C#实现多线程的Web代理服务器实例
- c#实现多线程局域网聊天系统
- PHP使用CURL实现多线程抓取网页
- 浅解关于C#多线程的介绍
- 批处理程序中的“多线程”处理代码