当前位置:  技术问答>linux和unix

生产者消费者问题--进程并发性体现得不太好,请帮我看看...

    来源: 互联网  发布时间:2016-01-26

    本文导语:  在Qt3.0下进行的开发,主要代码如下: #include  #include #include   #include   #include   #include   #include   #include   #include  /*   pv_slot函数用信号量实现生产者和消费者的pv操作. */ void sem::pvSlot() {     int sem_set_id;  ...

在Qt3.0下进行的开发,主要代码如下:
#include 
#include
#include  
#include  
#include  
#include  
#include  
#include  
#include 

/*
  pv_slot函数用信号量实现生产者和消费者的pv操作.
*/
void sem::pvSlot()
{
    int sem_set_id; 
    int rc,child_pid; 
    QString str; 
    sem_set_id=semget(290,6,IPC_CREAT|0600); 
    if(sem_set_id==-1) {QMessageBox::information( this, "error",tr("创建失败"),QMessageBox::Ok);exit(-1); } 
    rc=semctl(sem_set_id,0,SETVAL,1); //设置互斥信号量初值
    if(rc==-1) {QMessageBox::information( this, "error",tr("设置失败"),QMessageBox::Ok);exit(-1);} 
    rc=semctl(sem_set_id,1,SETVAL,0); //设置满缓冲池初值
    if(rc==-1) {QMessageBox::information( this, "error",tr("设置失败"),QMessageBox::Ok); exit(-1);} 
  
    rc=semctl(sem_set_id,2,SETVAL,20); //设置空缓冲池初值
    if(rc==-1) {QMessageBox::information( this, "error","设置失败",QMessageBox::Ok); exit(-1);} 
    rc=semctl(sem_set_id,3,SETVAL,1); //设置通知对方退出信号量的初值
    if(rc==-1) {QMessageBox::information( this, "error","设置失败",QMessageBox::Ok); exit(-1);} 
    rc=semctl(sem_set_id,4,SETVAL,0); //设置生产产品数初值
    if(rc==-1) {QMessageBox::information( this, "error","设置失败",QMessageBox::Ok); exit(-1);} 
    rc=semctl(sem_set_id,5,SETVAL,0); //设置消费产品数初值
    if(rc==-1) {QMessageBox::information( this, "error","设置失败",QMessageBox::Ok); exit(-1);} 
    child_pid=fork(); //创建子进程
    switch(child_pid){
/*
  子进程--消费者.
*/
         case -1:exit(-1); 
         case 0: while(semctl(sem_set_id,3,GETVAL)){ 
                    cwait(sem_set_id,1); //同步p操作
                    cwait(sem_set_id,0); //互斥p操作
                    if(!semctl(sem_set_id,3,GETVAL)) exit(0); 
                    csignal(sem_set_id,5); 
                    c->setText(str.setNum(semctl(sem_set_id,5,GETVAL))); 
                    p->setText(str.setNum(semctl(sem_set_id,4,GETVAL))); 
                    b->setText(str.setNum(semctl(sem_set_id,1,GETVAL))+"/20");  
                    switch( QMessageBox::information( this, "continue",tr("希望继续消费吗?"), 
                    QMessageBox::Yes, QMessageBox::No)){ 
                         case QMessageBox::Yes: 
                         c->setText(str.setNum(semctl(sem_set_id,5,GETVAL))); 
                         b->setText(str.setNum(semctl(sem_set_id,1,GETVAL))+"/20"); 
                                      
                         break; 
                         case QMessageBox::No: 
                         semctl(sem_set_id,3,SETVAL,0); 
                                      
                         break; 
                                                  } 
                    csignal(sem_set_id,0); //互斥v操作
                    csignal(sem_set_id,2); //同步v操作
 
                                              } 
            // exit(0); 
 /*
   父进程--生产者.
 */
       default: while(semctl(sem_set_id,3,GETVAL)){ 
              cwait(sem_set_id,2); 
              cwait(sem_set_id,0); 
              if(!semctl(sem_set_id,3,GETVAL)) exit(0); 
              csignal(sem_set_id,4); 
              c->setText(str.setNum(semctl(sem_set_id,5,GETVAL))); 
              p->setText(str.setNum(semctl(sem_set_id,4,GETVAL))); 
              b->setText(str.setNum(20-semctl(sem_set_id,2,GETVAL))+"/20");  
              switch( QMessageBox::information( this, "continue",tr("希望继续生产吗?"), 
                    QMessageBox::Yes, QMessageBox::No)){ 
                    case QMessageBox::Yes: 
                    p->setText(str.setNum(semctl(sem_set_id,4,GETVAL))); 
                    b->setText(str.setNum(20-semctl(sem_set_id,2,GETVAL))+"/20"); 
                    break; 
                    case QMessageBox::No:  
                    semctl(sem_set_id,3,SETVAL,0); 
                    break; 
                              
                                                  } 
               csignal(sem_set_id,0); 
               csignal(sem_set_id,1); 
 
                                            } 
            // exit(0); 
             }
}

//v操作
void sem::csignal( int sem_set_id, int i )
{
    struct sembuf sem_op; 
    sem_op.sem_num=i; 
    sem_op.sem_op=1; 
    sem_op.sem_flg=0; 
    semop(sem_set_id,&sem_op,1); 
    return;
}
//p操作
void sem::cwait( int sem_set_id, int i )
{
    struct sembuf sem_op; //定义sem_op结构
    sem_op.sem_num=i; //信号量集的某个信号量
    sem_op.sem_op=-1; //负数代表占用资源,资源数量-1
    sem_op.sem_flg=0; //标志位
    semop(sem_set_id,&sem_op,1); //对信号量i进行一次操作
    return;
}
相关说明:
生产者-消费者问题是一个著名的进程同步问题。它描述的是:有一个生产者进程在生产消息,并将此消息提供给消费者进程去消费。为使生产者进程和消费者进程能并发执行,在它们之间设置了一个具有20个缓冲区的缓冲池,生产者进程可将它所生产的消息放入一个缓冲区中,消费者进程可从一个缓冲区中取得一个消息消费。尽管生产者进程和消费者进程,都是以异步方式运行的,但它们之间必须保持同步,既不允许消费者进程到一个空缓冲区去取消息,也不允许生产者进程向一个已装有消息且未被取走消息的缓冲区中投放消息。
利用进程通信机制中的信号量机制的系统调用实现缓冲区和互斥信号以及对他们的操作。
信号量机制的系统调用有:
创建信号量数组: 
sys_semget (key_t key, int nsems, int semflg)
调用接口为: 
semget(key_t key, int nsems, int semflg)
操作信号量数组: 
sys_semop (int semid, struct sembuf *tsops, unsigned nsops)
调用接口为: 
semop (int semid, struct sembuf *tsops, unsigned nsops)
设置信号量数组属性:
sys_semctl (int semid, int semnum, int cmd, union semun arg)
调用接口为:semctl (int semid, int semnum, int cmd, union semun arg)

利用sys_semget创建一个有6个信号量的信号量数组,分别表示互斥信号量、满缓冲区、空缓冲区、生产产品数、消费产品数以及一个生产者和消费者进程用来互相通知对方退出的信号量,利用sys_semctl设置6个信号量的初值,分别为1、0、20、0、0、1。定义函数cwait代表P操作,函数csignal代表V操作。在类Pvslot中定义一个方法pv()完成生产者-消费者过程的演示。
为了用图形化界面显示生产者-消费者的同步过程,用的是QtDesigner开发工具,定义的主框体为sem。图形界面包括一个开始按钮,这个按钮触发pv()函数,这个函数实现生产者-消费者问题的演示,一个显示生产产品数的文本框,一个显示消费产品数的文本框,一个显示缓冲区情况的文本框。当按下开始按钮时,开始进行过程演示,生产者进程与消费者进程随机对缓冲池进行请求操作,先得到互斥信号量的进程先操作;有一个原则:缓冲池空的时候,只有生产者进程进行生产;缓冲池满的时候,只有消费者进行消费。为了便于显示每一个生产和消费的操作,在进入生产进程或者消费进程的临界区时,都显示一个对话框,表示现在处于哪个进程,并询问是继续演示还是退出。
我的问题:
现在运行结果经常是生产者把缓冲池填满消费者才去消费,消费者把缓冲池取空,生产者才去生产。偶尔会出现生产者没有填满缓冲池,消费者抢到临界区的现象。这样一来,进程的并发性表现得不好,请问如何改进?谢谢!

|
没qt环境,你能不能改成命令行的。
我搞了个简单的,semid的各个含义跟你的一样。

        }else if( pid == 0 ){

                srand( time(NULL) );
                while( 1 ){
                        sleep( rand() % 3 );
                                                                                                                  
                        cwait( semid, 1 );                                                                        
                        cwait( semid, 0 );                                                                        
                                                                                                                  
                        printf( "Consumer: %d n", ++x );                                                         
                                                                                                                  
                        csignal( semid, 0 );                                                                      
                        csignal( semid, 2 );                                                                      
                }                                                                                                 
                                                                                                                  
                exit( 0 );
        }                                                                                                         
                                                                                                                  
        srand( time(NULL) );
        while( 1 ){
                sleep( rand() % 3 );
                                                                                                                  
                cwait( semid, 2 );                                                                                
                cwait( semid, 0 );                                                                                
                                                                                                                  
                printf( "Producter: %d n", ++x );                                                                
                                                                                                                  
                csignal( semid, 0 );                                                                              
                csignal( semid, 1 );                                                                              
        }                                                                                                         
                                                                                                                  
                                                                                                                  
        semctl( semid, 0, IPC_RMID );

    
 
 
 
本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 生产者与消费者
  • 生产者消费者问题...
  • linux下生产者消费者问题
  • 想实现类似“生产者、消费者”问题,应该如何设置buffer?
  • 一道题目的思考-“生产者消费者问题”
  • 单个生产者线程,单个消费者线程,用 cond、mutex还是sem?
  • JAVA生产者消费者(线程同步)代码学习示例
  • 300分!查错,解决多个生产者和多个消费者问题 高手进!分不够想法子再加!
  • java解决单缓冲生产者消费者问题示例
  • Lock、Condition实现简单的生产者消费者模式示例
  • 讨论一下如何实现一个生产者与两个消费者的问题(版主们一定要来看看)
  • 关于生产者与消费者问题
  • 关于生产者-消费者的程序
  • 用信号量同步生产者消费者的问题
  • 大家看看我的生产者消费者问题编程有没有问题....
  • 求助:有关linux下的线程编程问题-生产者消费者问题
  • 多个生产者与消费者的UNIX系统V编程实现问题
  • Linux c++ 消费者 生产者 互斥同步 问题
  • 深入多线程之:深入生产者、消费者队列分析
  • linux环境的生产者消费者问题


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3