2010-12-14 153 views
0

我编写代码来实现生产者 - 消费者问题,它似乎工作正常,无需同步。是否有可能?生产者 - 消费者使用同步

我该如何测试代码并检查它是否实际正常工作?我怎么知道是否会发生死锁?现在,我没有摆脱循环(即生产者继续插入并且消费者继续消耗在无限循环中)。为了简单起见,我使用了大小为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; 
    } 
} 
+1

它可能会陷入困境,如果你删除'Sleeps'。 – SwDevMan81 2010-12-14 18:59:55

+2

欢迎来到时间错误的本质。它似乎正在正常工作,直到它完全爆炸。 – 2010-12-14 19:00:35

+2

为什么不把生产者和消费者的逻辑分成两个独立的'Runnable'实现?这种设计非常不灵活,并且会导致完全无恶意的代码。 – 2010-12-14 19:01:38

回答

1

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

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

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

你的代码将正常工作,直到生产者和消费者同时尝试执行农产品()和消费()。换句话说,这可能不是很常见,但绝对有可能并且一定会发生!

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

+0

所以,这意味着它不能在我的实现中没有同步,并且在某些时候程序会崩溃? – collegian 2010-12-14 19:08:14

+1

是的。在实现线程和共享数据时,考虑一下“如果有一种方式来交叉线程,以至于它们会崩溃,调度程序就会找到它”。 – 2010-12-14 19:10:50

0

有没有这样的东西作为the Producer-Consumer problem。生产者 - 消费者是一种设计模式,可能是也可能不是有效实现问题的解决方案,而不是本身的问题。

我很确定有很多不需要同步的生产者 - 消费者实现。这完全取决于你想要完成什么以及你正在生产/消费什么样的数据。

另外,如果你想说没有同步的实现工作,你必须解决一个问题。在做什么工作?我不知道你在做什么。

+0

我只是想生产,然后消耗! – collegian 2010-12-14 19:01:39

+0

有趣的是,维基百科关于“生产者 - 消费者问题”的文章似乎不同意。 – 2010-12-14 19:25:27

+0

好像我的问题的定义与他们的不一样。我想这就是为什么我是一名工程师而不是计算机科学家。 – Falmarri 2010-12-14 19:34:39

0

它可以通过一个锁定空闲队列完成,但不是这样,我建议您阅读Java Concurrency in Practice。如果你的代码同时被多个线程访问,你会有很多错误,你有发布和syncronizations问题!但是像Farlmarri说的那样取决于这个代码的用法。

0

你实际上并没有解决生产者/消费者问题,只是在它周围走动:) 你的代码的工作原因是时机,并且因为如果两个线程中的一个线程无法放入/检索它请求的资源基本上睡了一会儿再试。虽然这种情况(当你不必立即处理一个事件时)会浪费CPU时间。

这就是为什么信号灯强烈建议解决此类问题的,你可以在这里阅读

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

再见

+0

实际上,它看起来像OP的实现非常类似于该文章中列出的实现“不足”。 – 2010-12-14 19:26:11