2017-08-30 48 views
-1

雖然在工作線程中使用一個簡單的互斥鎖和條件變量,但我的程序會收到一些罕見且零星的線程匱乏錯誤,但我想阻止它。Java中的「無飢餓」實現

以下是我正在做的一個簡單的例子。有4個工作線程調用「Producer」和一個調用prod.getTasks()的主線程。

此代碼是「無死鎖」,但由於錯誤,顯然不是「無飢餓」。

當我拿到檢測線程飢餓或時鐘飛躍(管家三角洲=1m18s317ms137μs765ns)錯誤是:

A)由於生產者線程是坐在一個等待狀態的時間過長? (我不這麼認爲,因爲我認爲一個線程在準備好使用之前可能會等待任意一段時間,肯定會超過1分鐘)。 B)因爲其中一個等待工作者線程已經被多次傳遞了嗎?

基本上任何好的提示,以幫助使這個飢餓免費將不勝感激。

class Producer implements Runnable 
{ 
    private static ArrayList<Task> arrTasks = new ArrayList<Task>(); 

    void getTasks() 
    { 
     Task t = getTask(); // get Tasks from a producer specific recordset.  
     synchronized (arrTasks) 
     { 
      arrTasks.add(t); 
      arrTasks.notify(); 
     } 
    } 

    void run() 
    { 
     while (true) 
     { 
      Task t = null; 

      synchronized (arrTasks) 
      { 
       if (arrTasks.size() == 0) 
        arrTasks.wait(); 

       if (arrTasks.size() > 0) 
        t = arrTasks.remove(0); 
      } 

      if (t != null) 
       processTask(t); 

      if (mExit) 
       break; 
     } 
    } 
} 
+1

代碼不完整。什麼是's_ptTasks'?另外,你在一個對象上wait(),在另一個對象上notify()。這個可以嗎? –

+0

@RomanPuchkovskiy:我的不好..我編輯它。 – paiego

+0

@NathanHughes這是對實際代碼的簡化,它可以正確使用保護塊。我也知道我可以使用更高級別的服務來處理併發。這只是一個關於飢餓的問題。 – paiego

回答

0

生產者/消費者模式總是要麼餓死,要麼過載,要麼毫無意義。這不是一個性能模式,它用於抽象。

如果您使用的concurrent BlockingQueue允許您刪除所有​​,那麼您的代碼可以變得更容易。

+0

實際的實現既沒有超載,也沒有意義,也沒有經常餓死。它每晚都有效地運行數百萬條記錄,並且只有一次顯示出飢餓。如果BlockingQueue也使用防護塊,我也不會感到驚訝。 – paiego