【转】信号量实现生产者消费者模式

Linux信号量机制(生产者消费者)

标签: linux产品nulljoinsignalini
 分类:
 

 

该程序为Linux信号量机制实现程序,主要模拟了一般的生产者-消费者问题。(生产者-消费者问题是一个经典的进程同步问题,该问题最早由Dijkstra提出,用以演示他提出的信号量机制。在同一个进程地址空间内执行的两个线程。生产者线程生产物品,然后将物品放置在一个空缓冲区中供消费者线程消费。消费者线程从缓冲区中获得物品,然后释放缓冲区。当生产者线程生产物品时,如果没有空缓冲区可用,那么生产者线程必须等待消费者线程释放出一个空缓冲区。当消费者线程消费物品时,如果没有满的缓冲区,那么消费者线程将被阻塞,直到新的物品被生产出来。

 

[html] view plain copy
 
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <unistd.h>  
  4. #include <pthread.h>  
  5. #include <semaphore.h>  
  6. #include <signal.h>  
  7.    
  8. #define N 5   // 消费者或者生产者的数目  
  9. #define M 10 // 缓冲数目  
  10. //int M=10;  
  11. int in = 0; // 生产者放置产品的位置  
  12. int out = 0; // 消费者取产品的位置  
  13.    
  14. int buff[M] = { 0 }; // 缓冲初始化为0,开始时没有产品  
  15.    
  16. sem_t empty_sem; // 同步信号量,当满了时阻止生产者放产品  
  17. sem_t full_sem; // 同步信号量,当没产品时阻止消费者消费  
  18. pthread_mutex_t mutex; // 互斥信号量,一次只有一个线程访问缓冲  
  19.    
  20. int product_id = 0; //生产者id  
  21. int prochase_id = 0; //消费者id  
  22. //信号处理函数  
  23. void Handlesignal(int signo){  
  24.     printf("程序退出\n",signo);  
  25.     exit(0);  
  26. }  
  27. /* 打印缓冲情况 */  
  28. void print() {  
  29.        inti;  
  30.        printf("产品队列为");  
  31.        for(i = 0; i M; i++)  
  32.               printf("%d", buff[i]);  
  33.        printf("\n");  
  34. }  
  35.    
  36. /* 生产者方法 */  
  37. void *product() {  
  38.        intid = ++product_id;  
  39.        while(1) {//重复进行  
  40.               //用sleep的数量可以调节生产和消费的速度,便于观察  
  41.               sleep(2);  
  42.    
  43.               sem_wait(&empty_sem);  
  44.               pthread_mutex_lock(&mutex);  
  45.    
  46.               in= in % M;  
  47.               printf("生产者%d在产品队列中放入第%d个产品\t",id, in);  
  48.    
  49.               buff[in]= 1;  
  50.               print();  
  51.               ++in;  
  52.    
  53.               pthread_mutex_unlock(&mutex);  
  54.               sem_post(&full_sem);  
  55.        }  
  56. }  
  57.    
  58. /* 消费者方法 */  
  59. void *prochase() {  
  60.        intid = ++prochase_id;  
  61.        while(1) {//重复进行  
  62.               //用sleep的数量可以调节生产和消费的速度,便于观察  
  63.               sleep(5);  
  64.    
  65.               sem_wait(&full_sem);  
  66.               pthread_mutex_lock(&mutex);  
  67.    
  68.               out= out % M;  
  69.               printf("消费者%d从产品队列中取出第%d个产品\t",id, out);  
  70.    
  71.               buff[out]= 0;  
  72.               print();  
  73.               ++out;  
  74.    
  75.               pthread_mutex_unlock(&mutex);  
  76.               sem_post(&empty_sem);  
  77.        }  
  78. }  
  79.    
  80. int main() {  
  81.        printf("生产者和消费者数目都为5,产品缓冲为10,生产者每2秒生产一个产品,消费者每5秒消费一个产品,Ctrl+退出程序\n");  
  82.        pthread_tid1[N];  
  83.        pthread_tid2[N];  
  84.        inti;  
  85.        intret[N];  
  86.        //结束程序  
  87.     if(signal(SIGINT,Handlesignal)==SIG_ERR){//按ctrl+C产生SIGINT信号  
  88.     printf("信号安装出错\n");  
  89.     }  
  90. // 初始化同步信号量  
  91.        intini1 = sem_init(&empty_sem, 0, M);//产品队列缓冲同步  
  92.        intini2 = sem_init(&full_sem, 0, 0);//线程运行同步  
  93.        if(ini1 && ini2 != 0) {  
  94.               printf("信号量初始化失败!\n");  
  95.               exit(1);  
  96.        }  
  97. //初始化互斥信号量  
  98.        intini3 = pthread_mutex_init(&mutex, NULL);  
  99.        if(ini3 != 0) {  
  100.               printf("线程同步初始化失败!\n");  
  101.               exit(1);  
  102.        }  
  103. // 创建N个生产者线程  
  104.        for(i = 0; i N; i++) {  
  105.               ret[i]= pthread_create(&id1[i], NULL, product, (void *) (&i));  
  106.               if(ret[i] != 0) {  
  107.                      printf("生产者%d线程创建失败!\n", i);  
  108.                      exit(1);  
  109.               }  
  110.        }  
  111. //创建N个消费者线程  
  112.        for(i = 0; i N; i++) {  
  113.               ret[i]= pthread_create(&id2[i], NULL, prochase, NULL);  
  114.               if(ret[i] != 0) {  
  115.                      printf("消费者%d线程创建失败!\n", i);  
  116.                      exit(1);  
  117.               }  
  118.        }  
  119. //等待线程销毁  
  120.        for(i = 0; i N; i++) {  
  121.               pthread_join(id1[i], NULL);  
  122.               pthread_join(id2[i],NULL);  
  123.        }  
  124.        exit(0);  
  125. }  

 

posted @ 2016-05-25 20:11  尾巴草  阅读(420)  评论(0编辑  收藏  举报