2010-12-14 150 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