私はを通して読んでてきたConcurency in Practice
ブライアン・ゲッツで。
ロックストライピングについての章では次のことが書かれているConcurrentHashMap
用途の16のバケットは、多くのスレッドによるマルチスレッドアクセスを改善するために:
ロック分割は、時にはそれがロックストライピングと呼ばれる場合には、独立したオブジェクトのvariablesized組のパーティションロックに拡張することができます。例えば、ConcurrentHashMapの実装は、ハッシュバケットの1/16を守るそれぞれが16のロックのアレイを使用します。バケットNは、ロックNによって守られている16国防省。
私はこれらの質問を読みました:
ConcurrentHashMapので作品を「ロックストライピング」どのように簡単な説明が必要
しかし、これらの答えは、Javaバージョン<= 7のために有効です。
Javaの場合8+動作が大幅に変更されているようです。Javaの場合8+(ロックがテーブルにないセグメントのためではなく、特定のノードのために取得していることと思われますtransient volatile ConcurrentHashMap.Node<K, V>[] table;
)。たとえばためのputVal
操作:
ConcurrentHashMap.Node var7;
.... ///retrive node for var7
synchronized(var7) {
....
}
そしてまた、Java8 +フィールドからのようなDEFAULT_CONCURRENCY_LEVEL
クラスは、とSegment
(それが唯一のプライベートメソッドで使用されている実装で未使用のようですwriteObject::ObjectOutputStream
し、この方法は、内の任意の場所に呼び出されていないConcurrentHashMap
実装)。
で、このような大きな変化の原因は何である
ConcurrentHashMap
の実装は?クラスが場合は
Segment
未使用であり、また、のようなフィールドはDEFAULT_CONCURRENCY_LEVEL
また、未使用である-実装からそれを取り除くない理由-それはいくつかの歴史的な理由のためにあるのですか?場合我々はそれがJavaバージョン<7のためにするために使用のように、十分な特定のノード上でのみロックされ、セグメントにはロックされていませんか?はいの場合 - なぜですか?それは我々がここでストライピングロックを必要としないことを意味するのでしょうか?
で、このような大きな変化の原因は何である
ConcurrentHashMap
の実装は?
* The primary design goal of this hash table is to maintain
* concurrent readability (typically method get(), but also
* iterators and related methods) while minimizing update
* contention.
Segment
クラスがあるため、互換性の理由で未使用のままConcurrentHashMap.java#L481:
* Maintaining API and serialization compatibility with previous
* versions of this class introduces several oddities. Mainly:
* [...]
* We also declare an unused "Segment" class that is
* instantiated in minimal form only when serializing.
...十分な特定のノード上でのみロックされて?はいの場合 - なぜですか?
* Using the first node of a list as a lock does not by itself
* suffice though: When a node is locked, any update must first
* validate that it is still the first node after locking it,
* and retry if not.