あなたの考えを教えてください。私が間違っている場合は修正してください。
楽観的ロックの実装原理は cas 操作であり、Java の軽量ロックも cas に基づいて実装されています。
悲観的ロックの最大の問題はブロッキングです。
Java 仮想マシンを深く理解すると、一般に軽量ロックは重量ロック (ミューテックス ロック) よりも優れており、同時実行性の高いロックの競争が激しい場合、軽量ロックは長いスピンを消費することになります。 CPU の影響により、軽量ロックのパフォーマンスが従来の重量ロックよりも遅くなります。次に、オプティミスティック ロックにはスピンとキャスも含まれるため、同時実行性が高い場合にはオプティミスティック ロックは良い解決策ではないようです。
ただし、一部のブログ投稿では、同時実行性が高い場合にはオプティミスティック ロックの方が適していると述べられています
たとえば、この記事では、同時実行性が高いデータベース アクセスにはオプティミスティック ロックを使用することが記載されています
http://blog.csdn.net/amqvje / a...
質問 1、同時実行性が高い場合、どのように選択すればよいですか?
質問 2 楽観的ロックの欠点は何ですか? なぜすべてが楽観的ロックを使用しないのでしょうか。同時実行性が高くない場合は、オプティミスティック ロックを使用しても問題はありません。
簡単に言えば、通常の状況では、楽観的ロックは読み取りのみで書き込みを行わない操作に適しており、悲観的ロックは読み取りと書き込みの混合操作に適しています。訪問者数の増加など、書き込み操作が非常に単純で短い場合、または読み取られたデータが最新であることを保証する必要がない場合は、楽観的ロックを使用することもできます。確かに、80% のケースではオプティミスティック ロックを使用する方が良い選択です。
CAS はアトミック レベルの操作を実装するためにハードウェア CPU 命令のサポートに依存しているため、同時実行性が高い状況では一般に高速になりますが、この速度には欠点がないわけではありません。 CPU がシングルコア (インテル以外のプラットフォームが組み込まれている) でない限り、速度が増加する可能性があります。
つまり、高い同時実行パフォーマンスを向上させるには、問題を説明するために実際に測定されたデータが必要です。上で述べたことはすべて理論にすぎません。お役に立てば幸いです。
悲観的ロックか楽観的ロックかは、実際には同時実行制御の考え方であり、楽観的ロックと悲観的ロックの具体的な選択はビジネス シナリオに基づいています。
オプティミスティック ロック:悲観的ロック:
一般に、私たちが使用する悲観的ロックは、ロックが成功した場合、データを変更でき、トランザクションが正常に送信され、ロックが解除された場合、トランザクションを送信できます。失敗はデータが変更されていることを意味します。 mysql の innodb を使用する場合は、mysql の自動コミット属性をオフにするように注意してください。これは、mysql がデフォルトで自動コミット モードを使用するためです。つまり、更新操作を実行すると、MySQL はすぐに結果を送信します。デフォルトでは、innodb は行レベルのロックを使用しますが、SQL がインデックスを使用しない場合、mysql はテーブルレベルのロックを使用してテーブルをロックします。
set autocommit=0
長所と短所:ペシミスティック ロックは、「最初にロックを取得してからアクセスする」という保守的な戦略であり、データ処理のセキュリティを保証します。ただし、効率の観点から見ると、ロック メカニズムによりデータベースに追加のオーバーヘッドが発生し、デッドロックが発生する可能性が高くなります。また、読み取り専用のトランザクション処理では競合が発生しないため、システム負荷が増大するだけのロックを使用する必要がありません。また、トランザクションが特定のデータ行をロックすると、他のトランザクションはそのデータ行を処理する前にトランザクションが処理されるまで待機する必要があります。
オプティミスティック ロックは、通常の状況ではデータが競合を引き起こさないことを実際に想定しているため、データが更新のために送信されると、データの競合が正式に検出され、競合が見つかった場合はユーザーが返されます。エラー情報を表示し、ユーザーが何をすべきかを決定します。
長所と短所:一般に、悲観的ロックと比較して、楽観的ロックはデータベースを処理する際にデータベースが提供するロック機構を使用せず、通常はバージョン番号またはタイムスタンプを使用して実装します。バージョン番号を使用する場合、データの初期化中にバージョン番号を指定でき、データの更新操作ごとにバージョン番号に 1 が加算されます。そして、現在のバージョン番号がデータの最新のバージョン番号であるかどうかを判断します。例:
リーリー
楽観的ロックでは、データ競合の可能性は非常に小さいと考えられているため、できるだけ直接的に続行し、送信されるまでロックを行わないため、ロックやデッドロックは発生しません。ただし、これを単純に実行した場合でも、予期しない結果が発生する可能性があります。たとえば、2 つのトランザクションがデータベースの特定の行を読み取り、変更後にデータベースに書き戻す場合、問題が発生します。
楽観的ロックの失敗は確率が低いイベントであり、発生するには複数の条件の協力が必要です。例:
ユーザー A が読み取りを完了した後、ユーザー B がたまたまレコードを削除しました。その後、ユーザー C が新しいレコードを挿入しました。
このとき、誤って、新しく挿入されたレコードのIDは、ユーザーAが読み込んだレコードのIDと一致しており、バージョン番号は両方ともデフォルト値の0です。
ユーザー C が操作を完了した後、ユーザー A は完了したレコードを変更して保存します。 ID とバージョンの両方が一致するため、ユーザー A は正常に保存されます。ただし、ユーザー C が挿入したレコードは上書きされました。
現時点での楽観的ロックの失敗の根本的な理由は、アプリケーションで使用されている主キー ID 管理戦略が、ごくわずかな範囲で楽観的ロックと互換性がないことです。
作業を始める前は、私も質問者と同じ考えを持っていました。実際の作業では、実際の高同時実行下でシステムの最も時間がかかる部分は、常にネットワーク接続、データベース クエリ、およびスレッドのアクティブスリープは、基本的に無視できます
。重要な質問は、事実は悲観的か楽観的かということです。
リソースの競争が激しく共有できない場合、楽観的ロックは大量のリクエストの期待を裏切るだけです。
リソースをめぐる競合がない場合 (これは必ずしも同時実行性のレベルに関係するわけではありませんが、ビジネスへの影響が大きくなります)、悲観的なロックは不必要なロックを意味します。リソースが元々共有可能だった場合 (たとえば、リソースが複数の読み取り専用パーティをサポートしている場合)、悲観的ロックは元の使用可能な時間を失うことを意味します。
私は JVM についてあまり知りません。しかし、「楽観的ロックには Spin と cas も存在する」とはどういう意味でしょうか? cas はスピンロックの実装方法ですが、なぜ並列化する必要があるのでしょうか? 「また」とはどういう意味ですか?悲観的ロックはブロック操作であり、スピンはなく、継続的に CPU を消費しません。