Chinaunix首页 | 论坛 | 博客
  • 博客访问: 526977
  • 博文数量: 96
  • 博客积分: 2102
  • 博客等级: 上尉
  • 技术积分: 1695
  • 用 户 组: 普通用户
  • 注册时间: 2012-04-11 22:12
文章分类

全部博文(96)

文章存档

2014年(2)

2012年(94)

分类: C/C++

2012-04-21 10:56:13

问题一:
生产者------消费者问题

分析:该问题的基本工作模式为:
                  如果缓冲区为空则消费者不能取;如果缓冲区为满则生产者不可以继续生产。
                  如果缓冲区曼,需要唤醒消费者;如果缓冲区为空则需要唤醒生产者        
                  N个缓冲区;
                  如果只有一个信号量empty时,则:empty = N,in表示生产者放入缓冲区的商品的个数、out表示消费者取出商品个数.in、out为共享变量。因此为了防止多个进程同时修改它们,将对他们的操作放在PV操作中。
        Producer:
                      p(empty) //如果empty==0,则生产者进程自我阻塞。
                       p(mutex)
                        in:=in+1;
                       v(mutex)
        Consumer:
                        v(empty)
                        p(mutex)
                        out:=out+1;
                        v(mutex)
小结:以上程序缺少了唤醒操作。因此引入多个信号量。用于唤醒阻塞的进程。
        Producer:
                      p(empty) //如果empty==0,则生产者进程自我阻塞。
                       p(mutex)
                        in:=in+1 mod N;
                       v(mutex)
                       v(full)

        Consumer:
                        p(full)
                        p(mutex)
                        out:=out+1 mod N;
                        v(mutex)

                        v(empty)
对于in、out取余的原因是为了用于循环。

实现程序--------(锁和PV信号量)
local.c 文件

点击(此处)折叠或打开

  1. #ifndef _LOCAL_H
  2. #define _LOCAL_H

  3. #include<pthread.h>
  4. #include<unistd.h>
  5. #include<stdio.h>
  6. #include<sys/types.h>
  7. #include<sys/ipc.h>
  8. #include<sys/msg.h>
  9. #include<sys/sem.h>

  10. union semun {
  11.     int val;
  12.     struct semid_ds *buf;
  13.     ushort *array;
  14. };
  15. typedef struct MES{
  16.     int num;
  17.     int sem1[5];//该程序只使用了两个信号集
  18. }MES;

  19. #define BUFF 3
  20. pthread_mutex_t mutex;

  21. struct sembuf sbuf1={0,-1,IPC_NOWAIT};
  22. struct sembuf sbuf2={0,1,IPC_NOWAIT};
  23. //信号在信号集中的索引、操作类型(释放或归还)、是否阻塞
  24. void *Producer_pthread(void *mes);
  25. void *Consumer_pthread(void *mes);
  26. int create_semaphore(char * path, int number, char c,union semun* sem);
  27. //创建了两个信号量集,empty为第一个、full为第二个
  28. #endif
文件:producer_constum.c

  1. #include"local.h"

  2. int create_semaphore(char * path, int number, char c,union semun* sem)
  3. {
  4. //如果number>0,表示empty信号量。
  5. //如果number = 0,表示full信号量。
  6.     key_t key;
  7.     int semid;
  8.     if((key = ftok(path,c))==-1) {
  9.         perror("ftok error\n");
  10.         return -1;
  11.     }
  12.     if((semid= semget(key,1,IPC_CREAT|0666))==-1) {
  13.         perror("segmet error\n");
  14.         return -1;
  15.     }
  16.     sem->val= number;
  17.     if(semctl(semid,0,SETVAL,sem)==-1){
  18.         perror("semctl error\n");
  19.         return -1;
  20.     }
  21.     return semid;
  22. }
  23.    
  24. void* Consumer_pthread(void *mes)
  25. {
  26.     int i =0;

  27.     while(i<10) {
  28.         semop(((MES*)mes)->sem1[1],&sbuf1,1);
  29.         pthread_mutex_lock(&mutex);
  30.         sleep(1);
  31.         printf("cumsumer: out = %d \n",((MES*)mes)->num+1);
  32.         ((MES*)mes)->num = (((MES*)mes)->num+1)%BUFF;
  33.         pthread_mutex_unlock(&mutex);
  34.         semop(((MES*)mes)->sem1[0],&sbuf2,1);
  35.         i++;
  36.         sleep(1);
  37.     }
  38.     return NULL;
  39. }
  40. void* Producer_pthread(void *mes)
  41. {
  42.     int i=0;
  43.     while(i<10) {
  44.         semop(((MES*)mes)->sem1[0],&sbuf1,1);
  45.         pthread_mutex_lock(&mutex);
  46.         printf("producer: in = %d \n",((MES*)mes)->num+1);
  47.         sleep(1);
  48.         ((MES*)mes)->num =(((MES*)mes)->num+1)%BUFF;
  49.         pthread_mutex_unlock(&mutex);
  50.         sleep(1);
  51.         printf("wakeup consumer\n");
  52.         semop(((MES*)mes)->sem1[1],&sbuf2,1);
  53.         i++;
  54.     }
  55.     return NULL;
  56. }
  57. int main()
  58. {
  59.     pthread_t produce , consume;
  60.     MES mes1,mes2;
  61.     union semun semopts1,semopts2 ;

  62.     pthread_mutex_init(&mutex,NULL);//建立具有默认值属性的
  63.     mes1.num= 0;
  64.     mes1.sem1[0]=create_semaphore(".", BUFF, 's',&semopts1);
  65.     mes1.sem1[1]=create_semaphore(".", 0, 'k',&semopts2);
  66.     mes2 = mes1;
  67.     if( pthread_create(&produce,NULL,Producer_pthread,(void*)&mes1)==-1)
  68.         printf("produce ceate fail\n");
  69.     if( pthread_create(&consume,NULL,Consumer_pthread,(void*)&mes2)==-1)
  70.         printf("consume create fail\n");

  71.     pthread_join(produce,NULL);
  72.     pthread_join(consume,NULL);
  73.     pthread_mutex_destroy(&mutex);
  74.     return 0;
  75. }
问题二:
读者-----------写者问题 (以缓冲区为媒介,实现读者和写者的交互)

分析:
           该问题的工作原则:如果缓冲区为空时,读者不能访问缓冲区并且需要唤醒写者
           如果缓冲区为满时,写者不能将信息写入缓冲区且需要唤醒读者
           如果读者此时占有缓冲区,那么只允许读者进程访问该缓冲区
           如果写者进程占有缓冲区,那么不允许其他进程访问该缓冲区(其他进程包括:读者进程和别的写者进程)
            由上面分析到需要下面的变量:
                    wm=1 rm = 1 counter = 0 (共享变量) 
            实现:

              reader :
                       if(counter >=0)//读者进来,则阻塞写者进程 
                         p(wm);
                      p(rm)

                         counter +=1;
                       v(rm)
                       读
                      p(rm)//读者读完离开
                          counter -=1;
                      v(rm)
                     if(count==0)
                        v(wm);此时无读者进程,将写者进程唤醒。让读者和写者进程同时竞争资源
                   write :
                              p(rm)
                              p(wm)
                              写
                              v(wm)
                              v(rm)
     上面分析得因为写者进程和读者进程不可以并发执行 ,因此需要阻塞读者进程,因此会想到对rm信号量进行pv操作,但是如果要看能否运行写者进程的大前提已经在读者进程中实现了,因为只有counter=0时,才会唤醒写者进程。
                            只需要:
                             p(wm)

                              写
                             v(wm)
代码实现-----------------(锁、条件变量)
local_cond.h 文件

点击(此处)折叠或打开

  1. #ifndef _LOCAL_COND_H
  2. #define _LOCAL_COND_H
  3. #include<stdio.h>
  4. #include<pthread.h>
  5. #include<unistd.h>

  6. pthread_mutex_t rm ,wm;
  7. pthread_cond_t cond;

  8. void * Reader(void *counter);
  9. void * Writer(void*arg);
  10. #endif
 reader_writer.c文件

点击(此处)折叠或打开

  1. #include"local_cond.h"

  2. void * Reader(void * counter)
  3. {
  4.     while(1) {
  5.     if(*((int*)counter) >=0)
  6.         pthread_mutex_lock(&wm);
  7.     pthread_mutex_lock(&rm);
  8.     pthread_cond_wait(&cond,&wm);
  9.     (*(int*)counter) +=1;
  10.     printf("reader is reading\n");
  11.     printf("Reader := %d\n",(*(int*)counter));
  12.     pthread_mutex_unlock(&rm);
  13.    
  14.     pthread_mutex_lock(&rm);
  15.     printf("reader left \n");
  16.     (*(int*)counter) -=1;
  17.     printf("Reader := %d\n",(*(int*)counter));
  18.     pthread_cond_wait(&cond,&wm);
  19.     pthread_mutex_unlock(&rm);
  20.     if((*(int*)counter)==0)
  21.         pthread_mutex_unlock(&wm);
  22.     sleep(1);
  23.     }
  24.     return NULL;
  25. }
  26. void* Writer(void *arg)
  27. {
  28.     while(1) {
  29.         pthread_mutex_lock(&wm);
  30.         pthread_cond_wait(&cond,&wm);
  31.         printf("Writer is writing\n");
  32.         pthread_mutex_unlock(&wm);
  33.         pthread_cond_signal(&cond);
  34.         sleep(1);
  35.     }
  36.     return NULL;
  37. }
  38. int main()
  39. {
  40.  pthread_t reader,writer;
  41.  int counter = 0;

  42.  pthread_mutex_init(&rm,NULL);
  43.  pthread_mutex_init(&wm,NULL);
  44.  pthread_cond_init(&cond,NULL);
  45.  
  46.  pthread_create(&writer,NULL,(void*)Writer,NULL);
  47.  pthread_create(&reader,NULL,(void*)Reader,(void*)&counter);

  48.  do{
  49.      pthread_cond_signal(&cond);
  50.  }while(1);

  51.  pthread_join(writer,NULL);
  52.  pthread_join(reader,NULL);
  53.  pthread_mutex_destory(&rm);
  54.  pthread_mutex_destory(&wm);
  55.  pthread_cond_destory(&cond);

  56.  return 0;
  57. }


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