この記事では主に Java の高同時実行ロックの 3 つの実装例を紹介します。編集者が非常に優れていると考えたので、参考として共有します。エディターをフォローして見てみましょう
基本スキル - 楽観的ロック
楽観的ロックは、このようなシナリオに適しています。読み取りでは競合はありませんが、書き込みでは競合が発生します。同時読み取りの頻度は書き込みの頻度よりもはるかに高くなります。
次のコードを例に挙げます。悲観的ロックの実装:
public Object get(Object key) { synchronized(map) { if(map.get(key) == null) { // set some values } return map.get(key); } }
楽観的ロックの実装:
public Object get(Object key) { Object val = null; if((val = map.get(key) == null) { // 当map取值为null时再加锁判断 synchronized(map) { if(val = map.get(key) == null) { // set some value to map... } } } return map.get(key); }
中級スキル - String.intern()
楽観的ロックは解決できません書き込み競合の問題も数多くありますが、多くのシナリオでは、実際にはロックは特定のユーザーまたは特定の順序のみに適用されます。たとえば、ユーザーは後続の操作を実行する前にセッションを作成する必要があります。ただし、ネットワーク上の理由により、ユーザー セッションを作成するリクエストと後続のリクエストはほぼ同時に到着し、並列スレッドが後続のリクエストを先に処理する場合があります。一般に、ユーザー sessionMap は、上記のオプティミスティック ロックのようにロックする必要があります。このシナリオでは、ロックをユーザー自体に制限できます。つまり、元の
lock.lock(); int num=storage.get(key); storage.set(key,num+1); lock.unlock();
が次のように変更されます。これは、データベース テーブル ロックと行ロックの概念により似ています。明らかに行ロックです。同時実行機能はテーブル ロックよりもはるかに優れています。
String.inter() の使用は、このアイデアの具体的な実装です。クラス String は文字列のプールを維持します。 intern メソッドが呼び出されたときに、この String オブジェクトと等しい文字列 (equals(Object) メソッドによって決定される) がプールにすでに含まれている場合は、プール内の文字列が返されます。 String が同じ場合、String.intern() は常に同じオブジェクトを返すため、同じユーザーのロックが達成されることがわかります。ロックの粒度は特定のユーザーに限定されるため、システムは最大の同時実行性を実現します。
でも、、、JDK は CopyOnWriteMap を提供していないのですが、なぜですか?以下に良い答えがあります。つまり、すでに ConcurrentHashMap があるのに、なぜ CopyOnWriteMap が必要なのでしょうか?
Fredrik Bromee はこう書いています これはユースケースによると思いますが、既に ConcurrentHashMap があるのに、なぜ CopyOnWriteMap が必要なのでしょうか? 多くのリーダーと 1 つまたは少数の更新のみを含む単純なルックアップ テーブルの場合は、これは良いことですフィット。コピーオンライトコレクションとの比較:読み取り同時実行性:コピーオンライトコレクションと同等。複数のリーダーがロックフリーの方法でマップから要素を同時に取得できます。書き込み同時実行性:基本的に更新をシリアル化するコピーオンライトコレクション (一度に 1 つの更新) よりも優れた同時実行性。ハッシュキーが均等に分散されている場合、複数の更新を同時に実行できる可能性が高くなります。書き込みマップのコピーの効果を得るには、常に同時実行レベル 1 で ConcurrentHashMap を初期化できます。
高度なヒント - クラス ConcurrentHashMap
String.inter() の欠陥は、クラス String が文字列を維持することです。プールは JVM パーマ領域に配置されます。ユーザー数が特に多い場合、文字列プールに配置された文字列が制御できなくなり、OOM エラーや過剰なフル GC が発生する可能性があります。ロックの数を制御し、ロックの粒度を下げるにはどうすればよいでしょうか? Java ConcurrentHashMap を直接使用しますか?それとも、独自のより詳細な制御を追加したいですか?次に、ConcurrentHashMap のメソッドから学び、ロックする必要があるオブジェクトを複数のバケットに分割し、各バケットにロックを追加します。疑似コードは次のとおりです。以上がJava は 3 つのメソッドを使用して高同時実行ロックのサンプル コードを実装します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。