说说我的看法,不对的地方请指正。
乐观锁的实现原理是cas操作,java中轻量级锁也是基于cas实现的。
悲观锁最大的问题就是阻塞问题。
在深入理解java虚拟机中提到,轻量级锁一般情况下是优于重量级锁(互斥锁)的;如果在高并发锁竞争比较激烈的情况下轻量级锁会由于长时间自旋消耗cpu 从而使得轻量级锁的性能比传统的重量级锁更慢。那么乐观锁中也有自旋和cas,所以高并发下乐观锁好像不是一种好的解决方案。
但是有些博文中提到 高并发下使用乐观锁更合适
比如这篇文章中就提到高并发数据库访问使用乐观锁
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 を消費しません。