Chinaunix首页 | 论坛 | 博客
  • 博客访问: 536524
  • 博文数量: 142
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1452
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-12 16:28
文章分类

全部博文(142)

文章存档

2016年(10)

2015年(60)

2014年(72)

我的朋友

分类: C/C++

2014-12-23 10:51:15

多生产者单消费者

点击(此处)折叠或打开

  1. #include "../unipc.h"

  2. #define NBUFF 10
  3. #define MAX_PRODUCE 100
  4. #define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
  5. int nitems;
  6. int nproducers;
  7. struct {
  8.     int index;
  9.     int buff[NBUFF];
  10.     sem_t mutex,nempty,nstored;
  11. } shared;

  12. void *produce(void *arg)
  13. {
  14.     for(;;) {
  15.         sem_wait(&shared.nempty);
  16.         sem_wait(&shared.mutex);
  17.         if(shared.index >= nitems){
  18.             sem_post(&shared.nempty);
  19.             sem_post(&shared.mutex);
  20.             return NULL;
  21.         }
  22.         shared.buff[shared.index %NBUFF] = shared.index;
  23.         shared.index++;
  24.         sem_post(&shared.mutex);
  25.         sem_post(&shared.nstored);
  26.         (*(int*)arg)++;
  27.     }
  28. }

  29. void *consume(void *arg)
  30. {
  31.     int i;
  32.     for(i = 0;i < nitems; i++) {
  33.         sem_wait(&shared.nstored);
  34.         sem_wait(&shared.mutex);
  35.         if(i != shared.buff[i%NBUFF]) {
  36.             printf("i = %d,buff[%d]=%d\n",i,i,shared.buff[i]);
  37.         }
  38.         sem_post(&shared.mutex);
  39.         sem_post(&shared.nempty);
  40.     }
  41.     return NULL;
  42. }

  43. int main(int argc ,char *argv[])
  44. {
  45.     int i;
  46.     int count[MAX_PRODUCE];
  47.     pthread_t ptid_produce[MAX_PRODUCE],ptid_consume;

  48.     if(argc != 3) {
  49.         printf("usage produce3 <#produces> <#items>\n");
  50.         return -1;
  51.     }
  52.     nproducers = atoi(argv[1]);
  53.     nitems = atoi(argv[2]);
  54.     if(nproducers > MAX_PRODUCE)
  55.         nproducers = MAX_PRODUCE;
  56.     printf("nproducers = %d,nitems=%d\n",nproducers,nitems);
  57.     sem_init(&shared.mutex,0,1);
  58.     sem_init(&shared.nempty,0,NBUFF);
  59.     sem_init(&shared.nstored,0,0);
  60.     shared.index = 0;

  61.     for(i = 0;i < nproducers; i++) {
  62.         count[i] = 0;
  63.         pthread_create(&ptid_produce[i],NULL,produce,&count[i]);
  64.     }
  65.     pthread_create(&ptid_consume,NULL,consume,NULL);

  66.     for(i = 0;i < nproducers; i++) {
  67.         pthread_join(ptid_produce[i],NULL);
  68.         printf("count[%d] = %d\n",i,count[i]);
  69.     }
  70.     pthread_join(ptid_consume,NULL);

  71.     sem_destroy(&shared.mutex);
  72.     sem_destroy(&shared.nempty);
  73.     sem_destroy(&shared.nstored);
  74.     return 0;
  75. }
生产者线程的终止

当最后一个条目生产出来后,每个生产者线程都执行循环顶端的语句:

sem_wait(&shared.nempty);

它将nempty信号量减1。
1.)然而每个生产者线程在终止前必须给该信号量加1(sem_post(&shared.nempty)),因为它在最后一次走过循环时并没有往缓存区存入一个条目。要是线程终止时我们没有给nempty信号量加1,而且生产者线程数大于缓冲区槽位数(譬如说14个生产者和10个缓冲区槽位),那么多余的线程(4个)将永远阻塞,等待nempty信号量,从而永远终止不了。

点击(此处)折叠或打开

  1. if(shared.index >= nitems){
  2.             //sem_post(&shared.nempty);
  3.             sem_post(&shared.mutex);
  4.             return NULL;
  5. }
注释掉sem_post(&shared.nempty); 运行produce3 14 10000
发现程序阻塞起来了
gwwu@hz-dev2.aerohive.com:~/test/mutex/pxsem>gcc -g produces3.c -o produces3 -Wall -pthread
gwwu@hz-dev2.aerohive.com:~/test/mutex/pxsem>./produces3 14 100000                         
nproducers = 14,nitems=100000
count[0] = 6994
count[1] = 7056
count[2] = 7079
count[3] = 7460
-----阻塞
通过查看线程的命令查看,发现一共有5个线程存在着,应该是一个主线程main,另外4个是生产者线程。

gwwu@hz-dev2.aerohive.com:~/codes/ipv6_12_11>ps -eLf | grep pts/3
gwwu      8529 25419  8529  0    5 10:39 pts/3    00:00:00 ./produces3 14 100000
gwwu      8529 25419  8534  0    5 10:39 pts/3    00:00:00 ./produces3 14 100000
gwwu      8529 25419  8535  0    5 10:39 pts/3    00:00:00 ./produces3 14 100000
gwwu      8529 25419  8539  0    5 10:39 pts/3    00:00:00 ./produces3 14 100000
gwwu      8529 25419  8542  0    5 10:39 pts/3    00:00:00 ./produces3 14 100000
gwwu      8561 25756  8561  0    1 10:41 pts/7    00:00:00 grep pts/3
gwwu     25395 25393 25395  0    1 09:49 ?        00:00:00 sshd: gwwu@pts/3 
gwwu     25419 25395 25419  0    1 09:49 pts/3    00:00:00 -bash
gwwu@hz-dev2.aerohive.com:~/codes/ipv6_12_11>

用pstree 查看更加明显:
gwwu@hz-dev2.aerohive.com:~/codes/ipv6_12_11>ps -t pts/3             
  PID TTY          TIME CMD
 8529 pts/3    00:00:00 produces3
25419 pts/3    00:00:00 bash
gwwu@hz-dev2.aerohive.com:~/codes/ipv6_12_11>pstree -p 8529
produces3(8529)-+-{produces3}(8534)
                |-{produces3}(8535)
                |-{produces3}(8539)
                `-{produces3}(8542)


2.)假设只有一个生产者,当它用完所有NBUFF后,将阻塞在sem_wait(&shared.nempty),等待消费者消费完处理sem_post(&shared.nempty).当生产者完成所有nitem个数据的生成后,最终由于消费者没有来得急消费,使得该生产者阻塞于sem_wait(&shared.nempty),等待最终消费者sem_post,然后进入if(shared.index >= nitems),然后退出。

阅读(462) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~