Linux信號量機制(生產者消費者)

轉自 http://blog.csdn.net/hc260164797/article/details/7566850


該程序爲Linux信號量機制實現程序,主要模擬了一般的生產者-消費者問題。(生產者-消費者問題是一個經典的進程同步問題,該問題最早由Dijkstra提出,用以演示他提出的信號量機制。在同一個進程地址空間內執行的兩個線程。生產者線程生產物品,然後將物品放置在一個空緩衝區中供消費者線程消費。消費者線程從緩衝區中獲得物品,然後釋放緩衝區。當生產者線程生產物品時,如果沒有空緩衝區可用,那麼生產者線程必須等待消費者線程釋放出一個空緩衝區。當消費者線程消費物品時,如果沒有滿的緩衝區,那麼消費者線程將被阻塞,直到新的物品被生產出來。

[html] view plaincopy
  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.               inin % 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.               outout % 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. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章