同期リストにアクセスしようとするとスレッドが停止するのはなぜですか?
-
22-07-2019 - |
質問
何らかの理由で、この出力:
public void msgNeedParts() {
// Blabla...
System.out.println(name + ": Try to print 'tasks'...");
synchronized(tasks) {
System.out.println(name + ": Tasks--" + tasks);
System.out.println(name + ": Did I manage to print it?");
tasks.add(new BinToDump(feeder, binNum));
}
stateChanged();
}
「GantryAgent:「タスク」を印刷してみてください...」ただし、次のメッセージは含まれません。同期リストの「タスク」にアクセスしようとすると、スレッドがどういうわけか「スタック」するのではないかと推測していますが、なぜこれが起こっているのかわかりません。
'tasks'は次のように宣言および初期化されました:
private List<BinToDump> tasks =
Collections.synchronizedList(new ArrayList<BinToDump>());
誰かが私に欠けているものを指摘できますか?
ああ!犯人がいるかもしれない:
/* If nothing left to do, return to original position. */
synchronized (tasks) {
if (tasks.isEmpty()) {
doReturnToOriginalPos();
}
}
スケジューラー(これはエージェント設計です)で、「タスク」が空かどうかを確認してから、doReturnToOriginalPos()を呼び出します。たぶん、これは他の方法では変更できないため、何度も繰り返し発生しているのでしょうか?
それはまさに問題でした!それは私のスケジューラで非常に高速に呼び出され続け、他の誰も「タスク」にアクセスできませんでした。助けてくれてありがとう!
解決
何かがタスクをロックしています。これがどのような種類のアプリケーションであるかによって、システムの完全なスタックダンプを取得できるはずですが、方法は異なります。たとえば、ほとんどのWindowsベースのアプリサーバーでCTRL-Breakを使用するとこれが可能になり、LinuxでSIGQUITを送信しても同じことができると思います。
スタックダンプを取得したら、それを調べて、そのオブジェクトをロックしている他のスレッドを見つけることができます。
VisualVM も使用できます。同じ最終目標のスタックダンプを取得するには:
Java VisualVMを使用して、 スレッドダンプ(スタックトレース) ローカルアプリケーションが実行されています。取って スレッドダンプは停止しません 応用。スレッドを印刷するとき ダンプして、スレッドのプリントアウトを取得します のスレッド状態を含むスタック Javaスレッド。
Javaでスレッドダンプを印刷する場合 VisualVM、ツールはスタックを印刷します のアクティブなスレッドのトレース 応用。 Java VisualVMを使用して スレッドダンプを取ることは非常にできます しない場合に便利 のためのコマンドラインコンソールを持っています 応用。スタックトレースを使用できます 多数の問題の診断に役立ちます デッドロックなど、または アプリケーションがハングします。
他のヒント
別のスレッドが tasks
に対して同期ロックを保持している可能性はありますか?