Pergunta

I wrote code to implement the Producer-Consumer problem and it seems to be working fine without the need to synchronize.Is it possible?

How do I test the code and check if it is actually working right or not? How do I know if deadlock will occur? Right now,I am not breaking out of the loops(i.e. the Producer keeps inserting and the consumer keeps consuming in an infinite loop).I am using a circular queue of size 3(for sake of simplicity) as the shared resource.

Here is my code:

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;
     }
} 
Foi útil?

Solução

What you have tried to do is implement synchronization using busy-waiting. In pseudo code what you are basically doing is:

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

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

You code will work fine, till the the Producer and Consumer simultaneously try to execute produce() and consume(). In other words, either one of the This might not be very often, but is definitely possible and will definitely happen!

In Java, ConcurrentLinkedQueue to implements a wait-free algorithm for a shared buffer. I'm sure that are other implementations if you look around.

Outras dicas

There's no such thing as the Producer-Consumer problem. Producer-Consumer is a design pattern that may or may not be an effective implementation of a solution to a problem, not a problem in and of itself.

I'm SURE there are plenty of producer-consumer implementations that don't require synching. It entirely depends on what you're trying to accomplish and what kind of data you're producing/consuming.

Also, you have to have a problem to solve if you want to say you're implementation works without synchronizing. Works at doing what? I have no idea what you're doing.

It can be done with a lock free queue, but not like this, i recommend that you read Java Concurrency in Practice. If your code is access by multiple threads at the same time you will have many erros on that, you have publication and syncronizations problems!! But like Farlmarri said it depends on the usage of this code.

you are actually not solving the producer/consumer problem but just walking around it :) Your code works because of the timing and because of the fact if one of the two threads fails putting/retrieving the resource it asks for it basically sleeps for a while and tries again. Although this worsk (when you do not have to immediatly handle an event) it wastes CPU time.

That is why semaphores are strongly suggested to address this kind of issue as you can read here

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

bye

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top