2017-05-08 10 views
0

スレッドが実行されると、モニタのリンクリストに入れられるMessageオブジェクトが作成されます。同時に、他の2つのスレッドは、このリストがMessageオブジェクトを取得するのを待ちます。(linkedlist.isEmpty())canGetMessage.await();私はcanGetMessage.signalAll()を送信していますが、コマンドを使用すると、オブジェクトをリストに入れても、他の2つのスレッドは起きることはありません。スレッド条件が起こらない

public void deliverMessage(Message m){ 
lock.lock(); 

try{ 
    linkedlist.add(m); 
    canGetMessage.signalAll(); 
}finally{ 
    lock.unlock(); 
} 
} 


public Message getMessage(){ 
lock.lock(); 

try{ 
while(linkedlist.isEmpty()){ 
    canGetMessage.await(); 
    } 
return linkedlist.remove(); //returns the item that has been in the list the longest 
} 
catch (InterruptedException e) { } //not required to handle these 

finally{ 
lock.unlock(); 
} 

私はそれがwhileループを抜けたときに見にprintlnをしましたが、この問題が発生したことがない、と私はなぜ...

編集知りません:だけを指定する、私は」ロックを使用は再入可能ロックです

+2

はなぜいけませんプロデューサ - コンシューマパターンでBlockingQueueを使用しますか? –

+1

問題を再現する完全な最小例を投稿してください。 –

+0

'lock'、' linkedlist'と 'canGetMessage'はどのような型ですか、どのように作られていますか?そして、はい、[MCVE](http://stackoverflow.com/help/mcve)は非常に便利です。 – yeputons

答えて

0

推測;あなたはここに問題がある:

lock.lock(); 

場合には、送信側/受信側が、これは動作しないことができる同じロックオブジェクトを使用します。レシーバロックを取得します。送信者が新しいエントリをリストに追加するまでそれを解放しません。

しかし、送信者はその部分に到達できません。送信者がロックを既にロックされているロックにロックしようとするためです。ロックされたロックはブロックされます。

「正しい」回答は、「キューのような」ものを再発明する代わりに、BlockingQueueを使用して送信者/受信者を接続することです。 BlockingQueueの使い方の詳細については、hereを参照してください。

+1

いいえ、canGetMessage.await()はロックを解除します(条件がそのロックから作成されたと仮定します)。 –

+0

おそらく... OPが言っていることを見てみましょう。それが彼を助けないなら、私は答えを削除する気にしない。 – GhostCat

+2

@Telanore別のロックを使用しないでください。説明が必要な場合は、問題を再現する完全な最小例を投稿してください。あるいは、BlockingQueueを使用してください(これは私が同意すると、とにかく優れたソリューションです)。 –

0

皆さんに私の謝罪、それは問題は、スレッド自身の創造に横たわっていた、私はうっかり同じものを使用して、代わりにそれらすべてのスレッドごとに別々のモニターを作っていたが判明し...

+1

あなたは質問と自己回答を向上させたいのですが、おそらくあなたの質問を削除してください。 – GhostCat

関連する問題