休止状態を使用して、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 つしかないため、休止状態がこれをデッドロックとして報告する理由について特に混乱しています。
これに関するアイデアは大歓迎です!