トランザクションの一部として2つのアカウント間で転送を行う必要があるとします。
一般的なマルチスレッド環境では、複数の同様のトランザクションが同時に実行されます。
通常の慣例は(事前に設計された慣例どおりロック秩序の維持)として下記のようになります。原子的に複数のロックを取る
lock account A
lock account B
transfer(A,B)
release B
release A
はアトミック操作としてロックと解除を試みる方法はありますか?
トランザクションの一部として2つのアカウント間で転送を行う必要があるとします。
一般的なマルチスレッド環境では、複数の同様のトランザクションが同時に実行されます。
通常の慣例は(事前に設計された慣例どおりロック秩序の維持)として下記のようになります。原子的に複数のロックを取る
lock account A
lock account B
transfer(A,B)
release B
release A
はアトミック操作としてロックと解除を試みる方法はありますか?
はいあります:ロックの下でロックをロックする必要があります。つまり、ロック階層を作成する必要があります。しかし、この解決策は、ロックの細分性を低下させるのであまり効率的ではありません。
あなたの場合、常に同じ順序でロックを取ることで十分です。たとえば、常に最初にIDの小さいユーザーをロックします。
トランザクションはACID定義(アトミック性の場合)によってアトミックです。アイソレーション(少なくともREAD_COMMITED
)は、アカウントAに対して同時に発生する可能性のある他のトランザクションが、前回開始されたトランザクションが終了するまで待機することを保証します。したがって、実際には、内部実装(データベースなど)によってロックされるため明示的にロックする必要はなく、オプティミスティック・ロック手法を使用できるため、より効率的なロックになります。
しかし、これはすべてが1つのトランザクションコンテキスト(たとえば、JTA
環境など)に参加している場合にのみ当てはまります。そのような環境では、転送方法の始めにトランザクションを開始するだけで、アカウントAとアカウントBをロックする必要はありません。
同じトランザクションコンテキストにない場合、別のロックオブジェクトを導入できますアカウントAとBを使用していてもスレッドCをロックしていても、スレッドはロックされますので、パフォーマンスが大幅に低下します。この状況を回避する方法はあります(ConcurentHashMap
を参照してください。たとえば、 のロックがバスケット - オブジェクト全体ではありません)。
しかし、あなたの特定の例では、いくつかの一般的な考えだけがあります。私は、アカウントAとアカウントBを特定の順序でロックしていると思います(デッドロックが発生する可能性があるため、非常に注意してください)。与えられた状況に対しては正常です。
私はOPが転送という意味のトランザクションという言葉を使用していると確信しています。この質問は、データベースまたは分散トランザクションに関するものではありません。 – Oleg
@Olegはい、そうではありません。いくつかの方法で原子ロックを取得することです。私は、実際には必要でないトランザクション(データベースと分散トランザクションは、答えの対象ではない単なる例である)で指摘しました。そして非トランザクション環境では、別のロックオブジェクトを導入するしか方法がないので、答えはそれ自体で与えられます。著者や他の人に関連するかもしれない追加情報だけで。それで何が間違っていますか? –
分かりません。恐らく何も関係がないと感じます。あなたは私にdownvoteを取り除くために十分に確信しました。 – Oleg
は私にXYの問題のように聞こえる。 –
他の誰かが逆の順序でロックするのは古典的なデッドロックの状況です。原子的かどうか。 – edharned