2

休止状態を使用して、Java サーバーで競合状態の一時的な回避策を講じようとしています。コードは最初は次のようになります。

s = sessionFactory.openSession();
Object o1 = dao.getMostRecentVersionOfObject(key, s);
if (o1.performSomeTimeConsumingTask() == Looks.Ok) {
    Transaction t = s.beginTransaction();
    dao.update(o1, s);
    t.commit();
}

元の問題は、2 つの異なるスレッドがほぼ同時に同じコード ブロックに到達した場合、両方が同じバージョンのオブジェクトを取得しようとするため、2 番目のスレッドは常に失敗することです。複数の負荷分散されたサーバーがあるため、この問題の実際の解決策は、分散ロック システムを使用して、バージョンの同期を維持し、トランザクションが互いに足を踏み入れないようにすることです。しかし、ユーザーはすでにこれが問題であることを認識しており、この問題の長期的な解決策を開発するには時間がかかるため、トランザクションの直前にオブジェクトが更新されたかどうかを確認することにより、一時的なハックを追加するというエグゼクティブ決定を下しました開始します。このバージョン チェックを実行するために、2 つ目のセッションを作成しました。更新があった場合は、2 番目のセッションを使用してオブジェクトにデータを入力します。s フィールドを保存します。したがって、新しいコードは次のようになります。

Session s = sessionFactory.openSession();
Session transactionSession = s;
Object o1 = dao.getMostRecentVersionOfObject(key, s);
int version = o1.getVersion();
if (o1.performSomeTimeConsumingTask() == Looks.Ok) {
    Session newerSession = sessionFactory.openSession();
    Object newerObject = dao.getMostRecentVersionOfObject(key, newerSession);
    if (newerObject.getVersion() > version) {
        // update fields...
        transactionSession = newSession;
    }
}
Transaction t = transactionSession.beginTransaction();
dao.update(o1, transactionSession);
t.commit();

このコードはいくつかの環境で機能しますが、デッドロックが報告されているため、最も重要な環境で失敗します。これは、メソッドへの 2 番目の同時要求さえない場合に発生します。2 番目のセッションが作成され、バージョンがチェックされ、最初のセッションがコミット トランザクションを実行している間は無視されます。この問題は環境の問題であると思われます (しかし、なぜそうなるのかはわかりません)、または休止状態が 2 番目のセッションの使用を好まないのですが、これは経験に基づいた推測にすぎません。トランザクションが 1 つしかないため、休止状態がこれをデッドロックとして報告する理由について特に混乱しています。

これに関するアイデアは大歓迎です!

4

1 に答える 1

0

元の問題は、2 つの異なるスレッドがほぼ同時に同じコード ブロックに到達すると、両方が同じバージョンのオブジェクトを取得しようとするため、2 番目のスレッドは常に失敗することです。

2 番目の解決策にも同じ問題があります。あなたはこれをやっている、

  1. 最新のオブジェクトを取得する
  2. バージョンが同じでない場合はフィールドを更新します
  3. 更新されたオブジェクトをコミットする

ステップ 2 を実行しているときに、他のスレッドがオブジェクトを更新した可能性があります。

これが起こらないようにしたい場合は、メソッドを同期する (最も好ましくない) か、次の手順を実行します。

Session s = sessionFactory.openSession();
Object o1 =s.get('o1s class',key,new LockOptions(LockMode.PESSIMISTIC_WRITE));
//Do whatever you want with o1
//Update o1
//commit

アイデアは、db.See docから更新用のロックを取得してオブジェクトを取得することです。楽観的ロックよりも悲観的ロックを使用することの長所と短所を認識しておく必要があります。

于 2012-09-26T08:20:23.427 に答える