0

銀行アプリケーションの負荷テスト/ベンチマークを実行しています。ConcurrentModificationException約 100 人の仮想ユーザーで実行すると、エラーの 1 つとして発生します。以下はスタックトレースです。

java.util.ConcurrentModificationException
    at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(LinkedHashMap.java:373)
    at java.util.LinkedHashMap$KeyIterator.next(LinkedHashMap.java:384)
    at java.util.AbstractCollection.toArray(AbstractCollection.java:124)
    at java.util.ArrayList.<init>(ArrayList.java:131)
    at my.package.AuthorizationHelper.getAuthModuleList

以下はgetAuthModuleList()、例外を引き起こしているセクションです。

private static final LinkedHashSet MODULE_SET = new LinkedHashSet();

public static List getAuthModuleList(..)
{
   MODULE_SET.clear();
   ....

   MODULE_SET.add(getAllrequiredModules());

   List userLevelModules = getAllUserLevelModules();

   if (userLevelModules != null) {
      MODULE_SET.addAll(userLevelModules);
   }

   userLevelModules = new ArrayList(MODULE_SET); //Exception here
   return userLevelModules;
}

モジュールは、最初に必要なものから順に実行する必要があるため、LinkedHashSet.

以下は、CME の原因についての私の理解です。

  1. ユーザー A のトランザクションは、このメソッドを呼び出します。
  2. 同時に、ユーザー B もこのメソッドを呼び出しました。
  3. ユーザー A が例外ラインに到達するまでに、ユーザー B による同時アクセスはすでに変更されていMODULE_SETます。
  4. 上記のため、ArrayList の実装は例外をスローします。

私の理解によると、機能を壊すことなく上記を防ぐためにコードをどのように変更する必要がありますか:

この行を変更します。

userLevelModules = new ArrayList(MODULE_SET);

このスニペットに:

LinkedHashSet moduleSetCopy = new LinkedHashSet(MODULE_SET);
// userLevelModules = new ArrayList(MODULE_SET);
userLevelModules = new ArrayList(moduleSetCopy);

だから私の質問は、

  • 私の分析は正しいですか?
  • コレクションの方法の 1 つを使用して同期コピーを作成する必要がありますか?それとも通常のコピーで十分ですか?

アプリケーションは、標準の Sun JDK ではなく、Oracle JRockit(R) (ビルド R28.2.5-20-152429-1.6.0_37-20120927-1915-windows-x86_64、コンパイル済みモード)を使用することに注意してください。本番レベルの環境をシミュレートする必要があるため、後者は使用しません。

更新:回答に関連するかどうかはわかりませんMODULE_SETが、メソッドの開始時にクリアされています。

4

1 に答える 1

0

ああ、うまくいけば、このアプリケーションを使用するのは私の銀行ではありません ;-)

とにかく、適切な同期またはロックなしで共有リソース (MODULE_SET) を変更しており、分析は正しいです。ただし、解決策は、モジュールのリストがユーザーまたは要求に依存している場合は共有リソースをまったく使用しないか、それが真のシングルトンである場合は一度初期化することです。

最初の代替案では、コードは次のようになります。

public static List getAuthModuleList(..)
{
    LinkedHashSet MODULE_SET = new LinkedHashSet();

    MODULE_SET.add(getAllrequiredModules());
    List userLevelModules = getAllUserLevelModules();

    if (userLevelModules != null) {
       MODULE_SET.addAll(userLevelModules);
    }
    userLevelModules = new ArrayList(MODULE_SET); //Exception here
    return userLevelModules;
 }
于 2013-07-24T10:03:58.100 に答える