2

私は以下の状況です。

MonthlySales永続オブジェクトを読み取り/更新できるスレッドがいくつかあります。問題は、これらのオブジェクトが存在しない可能性があり、要求に応じて動的に作成する必要があることです。
したがって、2 つの異なるスレッドが同じキー (つまり、同じ ID を持つ) に対応するエンティティを作成することになり、そのうちの 1 つがcommit に失敗します。私はこれが起こることを望んでいません。2 つのスレッドのうちの 1 つが競争に勝ち、もう 1 つが緩んで、オブジェクトがもう一方によって作成されるまで待ちたいと思います。

つまり、シリアル化されたトランザクションを実行したいのです。明示的な Java ロック (synchronizedブロック) を設定する必要がありますか?

私の現在のコードは次のとおりです。

MonthlySales ms = entityManager.find(MonthlySales.class, somekey);
if (ms == null) { // two threads might enter this block altogether
    ms = new MonthlySales();
    // prepare ms object populating its fields with default values
    entityManager.persist(ms);
    entityManager.flush();
}
entityManager.lock(ms, LockModeType.PESSIMISTIC_WRITE); // lock this object
                                                        // since we are going to update it
// do something with ms object
entityManager.getTransaction().commit();
entityManager.close();

手伝って頂けますか?

4

1 に答える 1

1

競合状態を回避する 1 つの方法は、ID が最小のスレッド / プロセス / などを優先させることです。

を使用してスレッドIDにアクセスできると思います

long threadID = Thread.currentThread().getId();

Javaのスレッド内から。これは、他のスレッドをブロックするよりも優れた競合状態の解決策です。これは、複数のスレッドを使用する目的が無効になるためです。

クリティカル セクション ベーカリー アルゴリズムを参照してください。

http://www.basicsofcomputer.com/critical_section_problem_in_operating_system.htm

JPAの場合、herehereによると、ベストプラクティスのアプローチは、同時に変更を試み、うまくいかない場合は例外をキャッチすることのようです。

于 2012-06-13T03:44:31.497 に答える