2017-08-30 3 views
-1

ワーカースレッドの単純なミューテックスと条件変数を使用している間、私のプログラムはまれで散発的なスレッドスターベーションエラーを取得します。Javaの "飢餓のない"実装

以下は、私がやっていることの簡単な例です。 4つのワーカースレッドが "Producer"を呼び出し、prod.getTasks()を呼び出すメインスレッドがあります。

このコードは「デッドロックフリー」ですが、エラーのため「明らかに飢餓状態」ではありません。

私はスレッド飢餓やクロック飛躍が検出された(家政婦デルタ=1m18s317ms137μs765ns)を取得エラーは次のとおりです。

A)プロデューサーのスレッドが長すぎるために待機状態に座っているので? (私はスレッドが使用準備が整う前に任意の時間を待つことができると信じているので、そうは思わない。確かに1分より長い)。

B)待機中のワーカースレッドの1つが何回も渡されたためですか?

基本的に、この飢餓を無料にするのに役立つヒントを教えてください。

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でもGuarded Blocksを使用している場合、私は驚くことはありません。 – paiego

関連する問題