悲観的および楽観的ロックとCASおよび同期

悲観的ロックと楽観的ロック

悲観的ロックとは何ですか?

いわゆるペシミスティックロックは常に最悪のケースを想定しています。データを取得するたびに、他の人がデータを変更し、ファントムリード、反復不能なリード、ダーティリードなどが発生すると考えられるため、データを取得するたびにロックすると、共有リソースは一度に1つのスレッドによってのみ使用され、他のスレッドがブロックされます。使用後、リソースを他のスレッドに転送します。Javaの同期ロックや再入可能ロックなどの排他ロックは、悲観的なロックのアイデアを実現します。

行ロック、テーブルロック、読み取りロック、および書き込みロックで使用されるこのロックメカニズムも、操作前にロックされます。

楽観的ロックとは何ですか?

いわゆる楽観的ロックは、最良の状況の仮定に注意を払い、データを取得するたびに、他の人がそれを変更しないと考えるため、ロックされませんが、更新中にこのデータに変更があるかどうかを判断し、バージョン番号メカニズムを使用しますCASアルゴリズムを使用して実装された楽観的ロックは、マルチリードアプリケーションタイプに適しており、スループットを改善できます。

競合がある場合は、競合がある場合は再試行し、成功するまでスピン操作を入力します。楽観的ロックで使用されるメカニズムはCASです。

データベースは、提供されたオプティミスティックロックと同様の書き込み条件メカニズムを提供します。javaでは、java.util.concurrent.atomicパッケージの下のアトミック変数クラスが、楽観的ロックの実装であるCASを使用します。

楽観的ロックの2つの一般的な実装

バージョン番号メカニズム:

一般に、データバージョン番号のwersion(バージョン)フィールドがデータテーブルに追加され、データが変更された回数を示します。スレッドAがデータを更新する場合は、データの読み取り中にバージョン値も読み取り、送信します。現在更新されているバージョンが、スレッドAによって初めて取得されたバージョン番号と同じかどうかを判断して、更新する権利があるかどうかを判断します。更新バージョン++の後で、条件を満たさない場合、更新できず、操作をスピンして、再試行を続けます。 ;

CASアルゴリズム:

CAS(Compare And Swap)の比較と置き換え

3つの基本的なオペランドを使用します。メモリアドレスV(操作する値)、古い期待値A(つまり、操作する値を最初にAに入れ、メモリに格納されているものと同じ)、変更する新しい値B;

動作原理:スレッドAがデータの値を1増やしたい場合、メモリアドレスVが10に等しいと仮定すると、古い期待値はメモリアドレスVの値をコピーすることであり、スレッドAの場合、古い期待値Aも10に等しくなります。まだ送信されていない場合、スレッドBはこの値を1増やしてコミットします。メモリアドレスVの値は11になります。スレッドAがコミットすると、メモリアドレスV = 11を古い期待値A = 10と比較します。 Vの実際の値、送信は失敗しました。

スレッドAはスピン操作を実行し、メモリアドレスVの値を再度取得します。2回目は、VとAを比較します。両者が等しい場合、スレッドAはSWAPを実行し、アドレスVの値を新しい値Bに置き換えます。

CASメカニズムアプリケーション:

アトミックシリーズ、ロックシリーズの低レベル実装、java1.6以降、Synchronizedがヘビーウェイトロックに変換される前に、CASメカニズムも使用されます。

CAS機構の欠点:

1.大規模なメモリのオーバーヘッドに、スピン状態が失敗した使用に入りますので、同時の場合よりも高く、サイクル、CPU圧力の多くをもたらすでしょう。

2.コードブロックのアトミック性を保証していない唯一の変数アトミック操作がアトミック全体のコードブロックは、このような更新原子が、彼らが同期を使用しなければならないことを保証する必要性などの複数の変数を保証されていない保証するためにCAS機構。

3.ABAの問題は、古い期待AとVは同じメモリアドレスのとき、最大の問題は、CAS、CASのメカニズムは、メカニズムの使用であるが、このデータにアクセスし、変更されていないではないことを保証することはできませんが、値が変更されていません、これはABAの問題です。

しかし、JDK1.5以降、AtomicStampedReferenceクラスはこの問題を解決しました。このクラス内では、AtomicReferenceleクラスのCASメカニズムに追加のタイムスタンプがあるためです。更新時には、タイムスタンプも更新する必要があります。アドレスVとタイムスタンプの両方が同じ条件を満たしている場合、書き込みは成功します。したがって、ABAの問題が発生しても、オブジェクトは繰り返し読み取られ、書き込まれ、その後、タイムスタンプが変更される限り、元の値に書き戻されます。これにより、不適切な書き込みを防止できます。 。

楽観的ロックと悲観的ロックのシナリオを使用する

楽観的ロックは、書き込みが少ない場合(マルチリードシナリオ)に適しています。競合がほとんど発生しない場合は、ロックのオーバーヘッドを節約し、システムの全体的なスループットを向上させます。

悲観的ロックは、競合が頻繁に発生する複数書き込みの状況に適しています。楽観的ロックが使用されている場合、競合が発生すると送信は失敗し、スピンし続け、多くのメモリを占有し、すべての一般的な上書きシナリオで悲観論を使用します。ロックはより適切です。

CASと同期

同期ロックとは何ですか?

同期同期ロックは、操作をアトミック操作にし、スレッドの安全性を実現します。同期キーワードは、ロックリソースを持たないスレッドをBLOCKED(ブロッキング)状態にし、ロックリソースの競合後にRUNNABLE状態を回復します。このプロセスには、オペレーティングシステムのユーザーモードとカーネルモードの変換では、コストが高くなります。

java1.6以降では、Synchronizedが重量ロックに変換される前にCASメカニズムも使用されます。

jdk1.6以降、同期ロックはスピンロックに適応するように最適化されました(スピンロック:スレッドの状態の変化による消費を減らすために、現在の操作は常に実行されます)。ロックが排除されます(共有データの競合の可能性はありません)。ロックは集中的に排除され、ロックの粗大化(継続的なロックは1つのロックのみに削減されます)、軽量ロック(競争の条件下では、同期および相互排除はCASによって排除されます)、バイアスされたロック(競争のない条件下では排除) CASが動作しない場合でも、全体の同期は相互に排他的です。

同期の実装の基礎となることは主にロックフリーキューに依存して、基本的な考え方は、競技終了後公正を犠牲にして少しロックスイッチを競争するために引き続き、スピン閉塞ですが、競合が少ないスレッドの場合には、高いスループットを受けCASと同様のパフォーマンスが得られ、深刻なスレッドの競合が発生した場合、パフォーマンスはCASよりもはるかに高くなります。

アトミック操作クラスが同期ロックを置き換えます

java.util.concurrent.atomicパッケージでは、AtomicBooleanやAtomicIntegerなどのAtomicで始まるラッパークラスが、それぞれブール型および整数型のアトミック操作に使用され、使用後は、同期同期ロックの効果を達成できます。この場合、コードのパフォーマンスはSynchronizedよりも良くなります。Atomic操作クラスの最下部は、楽観的ロックのCASメカニズムを使用することです。

CASの使用例と同期

リソースの競合が少ない場合、同期された同期ロックは、スレッドのブロックとウェイクアップの切り替え、およびユーザー状態とカーネル状態の切り替え操作を実行し、追加のCPUを消費します。CASはハードウェアに基づいており、カーネルに入る必要がなく、切り替えを必要としません。スレッドはスピンを操作する可能性が少ないため、パフォーマンスが向上します。

深刻なリソース競合の場合、CASスピンの可能性は比較的大きく、CPUリソースを浪費し、同期よりも効率が低くなります。

元の記事5件を公開 賞賛された4件 訪問18件

おすすめ

転載: blog.csdn.net/qq_45218334/article/details/105618508