Works with: 

複数のスレッドが同じリソースに同時にアクセスしようとすると、スレッドの競合が生じます。このページでは、AppDynamics を使用してスレッドの競合の問題を診断および解決する方法について説明します。 

スレッドの競合により生じるパフォーマンスの問題

マルチスレッド プログラミング手法は、非同期処理を必要とするアプリケーションで一般的に使用されています。このようなアプリケーションでは、各スレッドに固有のコールスタックがありますが、スレッドからロック、キャッシュ、カウンタなどの共有リソースにアクセスしなければならないこともあります。「スレッド相関の有効化」を参照してください。

このような場合、同期の手法を使ってスレッドの干渉を防ぐこともできますが、今度はスレッドどうしが共有リソースへのアクセスを奪い合う場合があります。その結果、アプリケーション パフォーマンスの低下やデータ整合性の問題が発生する可能性があります。  

AppDynamicsでは、ビジネストランザクションとサービスエンドポイントのスレッドの競合に関する問題を特定して解決できます。詳細については、Javaのマルチスレッドトランザクションのトレースを参照してください。

スレッドの競合の検出

AppDynamics は、インストゥルメント化されたアプリケーションのスレッドの状態に基づいてスレッドの競合を検出します。 

JVMにおける以下のブロック状態(待ち状態)が識別されます。

  • ロックの取得(MONITOR_WAIT
  • 条件の待機(CONDOR_WAIT
  • スリープ状態(OBJECT_WAIT
  • ブロッキングI/Oオペレーション

OBJECT_WAIT 状態はアプリケーションが次のいずれかをコールしたときにトリガーされます。

  • Thread.sleep
  • Object.wait
  • Thread.join
  • LockSupport.parkNanos
  • LockSupport.parkUntil
  • LockSupport.park

ビジネス トランザクション フロー マップの [Potential Issues] ペインに、潜在的なスレッドの競合の問題に関するコントローラからの警告が表示されます。ここからブラウザを使用して、ビジネストランザクションまたはサービスエンドポイントのブロックされたスレッドと待機中のスレッドに関する追加情報にアクセスし、パフォーマンス問題の原因を特定できます。  

以下のセクションでは、ブラウザを使用してビジネストランザクションとサービスエンドポイントの競合情報を表示する方法について説明します。

動画を見る:Java スレッドの競合のモニタリングと分析

トランザクションスナップショットでのスレッドの競合

スレッドの競合情報を表示するには

  1. トランザクション スナップショットのナビゲーションページで、[Potential Issues] ペインから Thread Contention の問題としてラベル付けされた項目を探します。時間の列には、ブロックされた時間(待ち時間)が表示されます。
    Potential Issues
  2. ブロックされたメソッドの詳細を表示するには、スレッドの競合の項目をクリックし、[Drill Down into Call Graph] を選択します。
    View Details
    コールグラフには、スレッドの競合に関する以下の情報が表示されます。
    • [Call Graph] ヘッダーの [Wait Time] と [Block Time] には、ビジネストランザクションの 1 つのセグメントにおけるスレッドの集計測定項目が表示される。
    • [Call Graph] ヘッダーの [Node] には、競合スレッドをホストしているノードの名前(上の例では PojoNode)が表示される。
    • [Time] 列には、メソッド自体に費やされた合計時間が表示される。
    • [Percent%] 列には、そのメソッドに費やされた時間がスレッドの全体時間における割合として表示される。 
    • [Thread State] 列には、メソッドのスレッドの競合に関する問題の程度が示される。灰色は問題なしを意味し、黄色から赤色までの網かけは、競合に関する問題の重大度を表す。
      (バーの上にマウスを合わせると、スレッドの状態を構成する要素が表示される。これにはデフォルトでブロック時間と待ち時間が含まれる。スレッドの状態の詳細に CPU 時間を含めるには、開発モードを有効にする必要がある。)

  3. スレッドの状態がブロック時間または待ち時間を示すメソッドを右クリックして [View Details.] を選択する。次のようなスレッドの競合の詳細ペインが表示される。

    Thread Contention

    スレッドの競合の詳細ペインでは、ブロックされたメソッドの名前が左上に表示され、[Thread Contention] の表に以下の情報が追加されます。

    エレメント意味
    ブロックしているスレッドブロックしているオブジェクトのロックを保持するスレッド
    ブロックしているオブジェクトブロックされたスレッドがアクセスを待っているオブジェクト。
    ブロック時間オブジェクトへアクセスするための待ち時間合計。
    行番号ブロックされたメソッドで、ブロックしているオブジェクトがアクセスされる行番号。
    上の例では、run が 114 行目のロックされたオブジェクトへアクセスしようとしていることを示す。

    この表で、ブロックしているスレッドの表示順は重要ではなく、コールの順番や時系列を表すものではありません。

開発モードでは、AppDynamics により java.util.concurrent.locks.ReentrantLock のような明確なロックが、[Call Graph] ビューの [Thread Details] のブロック時間ではなく待ち時間としてレポートされます。ビジネストランザクションをモニタリングしてロックの競合に関するパフォーマンスを分析する際には、この点を考慮する必要があります。

サービスエンドポイントでのスレッドの競合

AppDynamics では、サービス エンドポイント メソッドのスレッドの競合情報を表示できます。サービス エンドポイント メソッドは、コールグラフに次のアイコンで表されます。

サービスエンドポイントごとのスレッドの競合情報を表示するには、メニューバーから More >  Service Endpoints を選択します。 

競合情報のエクスポート

ビジネストランザクションのコールグラフをエクスポートすると、AppDynamics はトランザクションの競合情報も含めます。 

  • [Summary] ペインには、[ Block Time] のデータが含まれています。表示されるブロック時間は、コールグラフペインに表示されるブロックされたメソッドの全ブロック時間の合計です。
    Summary
  • コールグラフペインには、メソッドごとのブロック時間が表示されます。
    Call Graph