ロックのパフォーマンスを向上させるためのいくつかの提案
ロック保持時間を短縮する
必要な場合にのみ同期し、ロック保持時間を大幅に短縮し、ロック競合の可能性を減らし同時実行性を向上させます
たとえば、synchronize 同期ロックを使用して、オブジェクトが変数の状態を共有する必要があるときに追加するようにしてください。メソッド全体の前に synchronize を追加するのではなく、このメソッドを呼び出すオブジェクトを直接ロックすると、ロック競合の可能性が高くなります。
効率を向上させるために ReadWriteLock 読み取り/書き込み分離を使用することについて話しました
それはさらにロック分離戦略に拡張されます
排他的ロック分離のテクノロジーへの典型的なリファレンスシーンは LinkedBlockingQueue タスク キューであり、リンクされたリストに基づいて実装された無制限のタスク キューであり、その take() メソッドと put() メソッドはそれぞれキューのフロントエンドとテールエンドで動作します。補完的な効果があるため、jdk では、これら 2 つの操作に対して 2 つのロックが提供されます
たとえば、put() 操作のマルチスレッド実行では、putLock に対して最も多くの競合が必要となり、take 操作は takeLock に対して競合します。リソースのロックを 1 回限りのロック要求に統合できるため、アプリケーションとリリースのアクションの消費が削減されます。
/** Lock held by take, poll, etc */ private final ReentrantLock takeLock = new ReentrantLock(); /** Wait queue for waiting takes */ private final Condition notEmpty = takeLock.newCondition(); /** Lock held by put, offer, etc */ private final ReentrantLock putLock = new ReentrantLock(); /** Wait queue for waiting puts */ private final Condition notFull = putLock.newCondition();
for(int i=0;i<n;i++){ synchronized(lock){} }
に最適化されています
このテクノロジーの典型的なアプリケーション シナリオは、HashMap と比較してスレッドセーフであり、HashTable と比較して、スレッドセーフです。効率的な同時実行
Segment クラスは ReentrantLock クラス
を継承しているため、ロックの取得に失敗するとこのメソッドがハングするため、ロックを取得するときに直接ロックを使用することはありません。実際には、問題: セグメントをまたがる操作が必要な場合、つまりシステムがグローバル ロックを取得する必要がある場合、すべてのセグメントのロックを正常に取得することによってのみ、各セグメントのロック状態を確認する必要があります。グローバルな情報を取得できます。たとえば、ConcurrentHashMap の size() メソッドでは、すべてのサブセグメントのロックを取得する必要があります
CAS に基づく ConcurrentHashMap の jdk 1.8 実装put 操作の場合、キーに対応する配列要素が null の場合、キーに設定されます。 CAS 操作による現在値。 Key に対応する配列要素 (つまり、リンク リストの先頭またはツリーのルート要素) が null でない場合は、synchronized キーワードを使用して要素にロックを適用し、操作を実行します。 put 操作によって現在のリンク リストの長さが特定のしきい値を超える場合、リンク リストはツリーに変換され、それによってアドレス指定効率が向上します。
読み取り操作の場合、配列は volatile キーワードで変更されるため、配列の可視性について心配する必要はありません。同時に、各要素は Node インスタンスです (Java 7 の各要素は HashEntry です)。その Key 値とハッシュ値は、final によって変更され、変更後の可視性を気にする必要はありません。そのValueと次の要素への参照はvolatileによって変更され、可視性も保証されます。
サイズ操作: 各大きな配列はカウンターを維持します。put メソッドと Remove メソッドは両方とも、addCount メソッドを通じて Map のサイズを維持します。 size メソッドは、addCount メソッドによって保持される Map のサイズを sumCount を通じて取得します。ConcurrentHashMap でグローバル カウンターを使用する代わりに各配列にカウンターが含まれる理由は、ConcurrentHashMap の同時実行性を考慮するためであるという事実に特別な注意を払う必要があります。 このように、カウンターを更新する必要がある場合、 ConcurrentHashMap 全体をロックする必要はありません count は揮発性であることに注意することが重要です。そのため、count の更新は他のスレッドにすぐに表示されます
関連記事:
Java フレームワーク Bootstrap、jQuery、SpringMVC、Hibernate高いパフォーマンスの同時実行性
関連ビデオ:
以上がJava 同時実行性を学ぶ: ロックの最適化、ConcurrentHashMap、ロックの分離の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。