zoukankan      html  css  js  c++  java
  • 【转】信号量实现生产者消费者模式

    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("程序退出 ",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(" ");  
    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个产品 ",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个产品 ",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+退出程序 ");  
    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("信号安装出错 ");  
    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("信号量初始化失败! ");  
    95.               exit(1);  
    96.        }  
    97. //初始化互斥信号量  
    98.        intini3 = pthread_mutex_init(&mutex, NULL);  
    99.        if(ini3 != 0) {  
    100.               printf("线程同步初始化失败! ");  
    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线程创建失败! ", 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线程创建失败! ", 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. }  
  • 相关阅读:
    OpenStack对象存储管理手册(5) OpenStack对象存储系统管理3
    hdu1568Fibonacci
    智能手机中显示信号强度格数
    上篇日本人经营之道 一破坏对手的情绪乱其方寸
    基于Wince的计算器程序
    shell 字符串操作
    轻松记住大端小端的含义
    如何把手机变成你的救生设备
    PM是一个事实
    mysql 5.6 online ddl 测试
  • 原文地址:https://www.cnblogs.com/xiaoying1245970347/p/5528332.html
Copyright © 2011-2022 走看看