演習 1.4: スレッドのボトルネックの解決

始める前に、『演習 1.3: スレッドのボトルネックの識別』を完了する必要があります。

コードのデッドロックを突き止めるには、スレッド・ビューに加えて、プロファイル・モニターの UML2 シーケンス・ダイアグラム (オブジェクト対話ビューおよびスレッド対話ビュー) およびコール・スタック・プロファイル・リソースが使用できます。

このデッドロックを解決するには、まず、呼び出しを行っているメソッドと、問題に関与するオブジェクトがどれかを検出します。

  1. スレッド・ビューで「ロック待ち」状態に入っている先頭の philo* スレッドを見つけます。カーソルを「ロック待ち」セグメント上に停止させます。スレッドが待っているロックが、ツールの説明によって識別されます (Fork.<id number>)。
  2. プロファイル・リソースを右マウス・ボタン・クリックし、「アプリケーションから開く」>「UML2 オブジェクト対話」を選択します。「UML2 シーケンス・ダイアグラム」ビューが開き、オブジェクト対話が表示されます。
  3. シーケンス・ダイアグラムでビューをスクロールして Fork.<id number> を見つけ、ダブルクリックして選択します。
  4. philo* スレッドの 1 つから Fork.<id number> への水平方向の矢印が見つかるまでスクロールダウンします。これらの矢印はオブジェクト間の相互作用を示し、これら 2 つのオブジェクト間での最初の相互作用は、philo* スレッドが Fork.<id number> を獲得したことを示します。getName というラベルの付いた矢印を見つけます。
  5. getName をダブルクリックします。スレッド・ビューで現在の時刻インディケーターを垂直方向に動かすと、getName が呼び出されたときに、プログラム全体で何が発生したかを参照できます。要求を行った philo* スレッドは「ロック待ち」状態に入っていないため、要求は成功したことが確認できます。
  6. シーケンス・ダイアグラムで Fork.<id number> を再度ダブルクリックし、別の philo* スレッドから発生した getName 要求が見つかるまでスクロールダウンします。
  7. getName のこのインスタンスをダブルクリックします。現在の時刻インディケーターには、要求を作成した philo* スレッドが Fork.<id number> を取得せず、「ロック待ち」状態に入ったことが示されます。

このインスタンスでは、別のスレッドによって保持されている Fork への要求が問題となっています。「ロック待ち」状態で終了した他のスレッドを確認して、このことが他のインスタンスにも該当するか検証します。

では、問題の原因となっているメソッドを見つけましょう。

  1. 実行するプロファイル・リソースを右マウス・ボタン・クリックし、「アプリケーションから開く」>「UML2 スレッド対話」を選択します。「UML2 シーケンス・ダイアグラム」ビューが開き、スレッド対話が表示されます。
  2. プロファイル・モニターでプロファイル・リソースを展開し、スレッド分析エントリーおよびコール・スタック・エントリーを展開します。
  3. スレッドの名前が表示されているスレッド・ビューで、「ロック待ち」状態に入っている先頭の philo* スレッドをダブルクリックします。「スレッド対話」ビューが、そのスレッドについてのみの情報を表示するように変更されます。
  4. スレッド情報の最後までスクロールダウンし、スレッドが実行した最後のメソッド (run メソッド) をダブルクリックします。プロファイル・モニターのコール・スタックに、そのときスタックにあるすべての呼び出しが表示されます。
  5. コール・スタックでは、ロックを保持しているスレッドは Philosopher.javaSleep メソッドを呼び出したこと、またスレッドはロックを待機しており、結果的には何もしないことに注意します。
  6. ロックを待った状態で実行を終了した別のスレッドを確認します。Philosopher.javaSleep メソッドは通常コール・スタック中にあり、これが問題となっています。

Sleep メソッドが疑わしいと思われます。ではコードを見てみましょう。

  1. コール・スタックで Sleep(int) void [Philosopher.java] のインスタンスを右マウス・ボタン・クリックし、「ソースを開く」を選択します。Sleep クラスの位置にあるソースがエディターで開きます。
  2. コードを調査してください。Sleep メソッドは run メソッド内部から呼び出されたことに注意します。まず trace への呼び出しが存在し、これが「got left...」というメッセージを出力し、その後 Sleep への呼び出しが存在します。Sleep への呼び出しをコメントにして取り除くことで、デッドロックが防止できる可能性があります。
  3. Sleep をコメントにして取り除きます。
  4. 「ファイル」>「保管」を選択します。
プログラムのプロファイルを再度作成します。

今回はデッドロックなしに実行され、コンソールに書き出します。

すべての philosopher が正常に実行を終了したことが HeadWaiter に報告されます。

お分かりの通り、スレッド・ビューと他のビューは、ご使用のプログラム実行時にスレッドに発生した内容を示します。次は、ご使用のプログラムに関する知識に基づいて分析を行い、デッドロックを解決します。

要約』に記載されている資料を確認してチュートリアルを完了します。

ご利用条件 | フィードバック
(C) Copyright IBM Corporation 2000, 2005. All Rights Reserved.
(C) Copyright IBM Japan 2005