生产者 - 消费者使用同步

时间:2010-12-14 18:55:42

标签: java synchronization producer-consumer

我编写了代码来实现Producer-Consumer问题,它似乎工作正常,无需同步。这可能吗?

如何测试代码并检查代码是否实际正常工作?我怎么知道是否会发生死锁?现在,我没有突破循环(即生产者继续插入,消费者继续在无限循环中消费)。我使用大小为3的循环队列(为简单起见)作为共享资源。

这是我的代码:

import java.util.*;

public class PCImpl implements Runnable 
{
Thread t;
QforPC qObj;

 public static void main(String[] args)
 {
     QforPC qObject=new QforPC();

     //These create 2 different objects! Each object has it's own thread of execution.
     //Synchronization is needed when 2 threads use the same object
    new PCImpl("Producer",qObject);
    new PCImpl("Consumer",qObject);
 }

 PCImpl(String name,QforPC qObj)
 {
     this.qObj=qObj;
     t=new Thread(this,name);
     t.start();
 }

 public void run()
 {
         if(Thread.currentThread().getName().equals("Producer"))
         {
             while(true)
             {
                  Random rgen=new Random();
                  int n=rgen.nextInt(100);
                  if(n!=0)
                              qObj.Producer(n);
                         try
                    {
                       Thread.sleep(200);
                     }
                      catch(InterruptedException e)
                    {

                    }
               }

            }


         if(Thread.currentThread().getName().equals("Consumer"))
         {
             while(true)
                  {
                 try
               {
                 Thread.sleep(1500);
               }
                catch(InterruptedException e)
               {
                  }
              qObj.Consumer();

              }
         }

  }
}



public class QforPC 
{
int[] q={0,0,0};
int r=0,f=0;
  public void Producer(int item)
     {

         if(r!=q.length && canProducer())
         {
             q[r]=item;
             System.out.println("The item inserted into the queue is:"+ item);
             r++;
         }
         if(r==q.length && f>0)
             r=0;
         else if(r==q.length && f==q.length)
         {
             r=0;
             f=0;
         }
     }

     public void Consumer()
     {
         int item;
         System.out.println("The value of isQueue empty is:"+ isEmpty());

         if(f!=q.length && isEmpty()==false)
         {
             System.out.println("Entered the consumer method");
             item=q[f];
             System.out.println("The item fetched from the queue is:"+item);
             q[f]=0;
             f++;
         }
         if(f==q.length && r<f)
             f=0;

     }

     public boolean isEmpty()
     {
         for(int k=0;k<q.length;k++)
         {
             if(q[k]==0 && k==q.length-1)
                 return true;

         }
         return false;
     }

     public boolean canProducer()
     {
         for(int k=0;k<q.length;k++)
         {
                 if(q[k]==0)
                 return true;

         }
         return false;
     }
} 

4 个答案:

答案 0 :(得分:1)

您尝试做的是使用忙等待实现同步。在伪代码中,你基本上做的是:

Producer()
{
   if (buffer.hasemptyspaces())
   {
      produce(buffer);
   }
   else
   {
      sleep(n);
   }
}

Consumer()
{
   if (buffer.hasfullspaces())
   {
      consume(buffer);
   }
   else
   {
      sleep(n);
   }
}

您的代码可以正常工作,直到Producer和Consumer同时尝试执行produce()和consume()。换句话说,其中任何一个可能不是很常见,但肯定是可能的,肯定会发生!

在Java中,ConcurrentLinkedQueue为共享缓冲区实现无等待算法。如果你环顾四周,我确信这是其他实现。

答案 1 :(得分:0)

没有the Producer-Consumer problem之类的东西。生产者 - 消费者是一种设计模式,可能是也可能不是解决问题的有效方法,而不是问题本身。

我确实有很多生产者 - 消费者实现不需要同步。这完全取决于您要完成的工作以及您正在制作/消费的数据类型。

此外,如果您想在没有同步的情况下说您的实施工作,则必须解决问题。在做什么工作?我不知道你在做什么。

答案 2 :(得分:0)

可以使用无锁队列来完成,但不是这样,我建议你阅读Java Concurrency in Practice。如果您的代码同时被多个线程访问,那么您将拥有许多错误,那么您就会遇到发布和同步问题!但是像Farlmarri说的那样取决于这段代码的用法。

答案 3 :(得分:0)

你实际上并没有解决生产者/消费者的问题,而只是走动它:) 您的代码因为时间而工作,并且因为如果两个线程中的一个未能放置/检索它要求的资源,它基本上会休眠一段时间并再次尝试。虽然这种情况很糟糕(当你不必立即处理事件时)它会浪费CPU时间。

这就是为什么强烈建议使用信号量来解决这类问题,因为你可以在这里阅读

http://en.wikipedia.org/wiki/Producer-consumer_problem

再见