ConcurrentMapの分析と思考

4352 ワード

予備知識:Java HashMap and HashSetの実現メカニズム
 
hashmapのストレージ構造は、次のように準備されていることがわかります.
   
ConcurrentMap 分析和思考
(画像はhttp://www.ibm.com/developerworks/cn/java/j-lo-hash/から)
 
つまり、hashmapの内部にはEntityクラス行の配列が含まれており、この配列の要素はEntityです.実際にmapに入れたkeyとvalueは、key、value、hashcode(key)、およびEntityの参照を含むEntityオブジェクトに対応しています.この参照により、Entityはチェーンテーブルを形成することができます.図では、青色の長方形のボックスは配列を表し、オレンジ色の楕円はEntityオブジェクトを表します.
 
HashMapクラスはスレッドが安全ではないことに注意してください.
 
 
ConcurrentMapの主なサブクラスはConcurrentHashMapです.
原理:1つのConcurrentHashMapは複数のsegmentからなり、各segmentは1つのEntityの配列を含む.ここではHashMapよりも1つのsegmentクラスが増えています.このクラスはReentrantLockクラスを継承しているので、それ自体がロックです.マルチスレッドがConcurrentHashMapに対して動作する場合、mapを完全にロックするのではなく、対応するsegmentをロックします.これにより、同時効率が向上します.
 
コンストラクション関数の解析:
 
 
  /** 



     * Creates a new, empty map with a default initial capacity (16), 



     * load factor (0.75) and concurrencyLevel (16). 



     */  



  public ConcurrentHashMap() {  



    this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR, DEFAULT_CONCURRENCY_LEVEL);  



    }  

 
 
 
 
これはConcurrentHashMapの無パラメトリック構造関数で、デフォルトのサイズは16、負荷係数は0.75、同時レベルは16であることがわかります.
 
 
Put関数の解析:
 
  /** 



     * Maps the specified key to the specified value in this table. 



     * Neither the key nor the value can be null. 



     * 



     * <p> The value can be retrieved by calling the <tt>get</tt> method 



     * with a key that is equal to the original key. 



     * 



     * @param key key with which the specified value is to be associated 



     * @param value value to be associated with the specified key 



     * @return the previous value associated with <tt>key</tt>, or 



     *         <tt>null</tt> if there was no mapping for <tt>key</tt> 



     * @throws NullPointerException if the specified key or value is null 



     */  



  public V put(K key, V value) {  



    if (value == null)  



    throw new NullPointerException();  



    int hash = hash(key.hashCode());  



    return segmentFor(hash).put(key, hash, value, false);  



    }  

 
 
 
 
hash()関数によりkeyのハッシュ値が得られ,対応するsegmentが得られ,segmentによりEntityが格納されることが分かる.
 
同時に、「検出再修正」(条件付きスレッドセキュリティ[2]参照)などの同時問題を回避するために、ConcurrentHashMapはputIfAbsent(K key,V value)メソッドを提供し、keyが存在しない場合に追加します.(keyの存在は2つの条件に依存し,1つはkeyのhashcode法,もう1つはkeyのequal法である)
 
 
利点:map全体をロックするのではなく、対応するsegmentにロックをかけることで、同時性が向上します.挿入、検索および除去操作の伸縮性を直接向上させることができる.
欠点:mapの要素を巡回する場合、すべてのsegmentのロックを取得する必要があります.巡回を使用するのは遅いです.ロックが増加し、システムのリソースを占有しています.セット全体を動作させるいくつかの方法、例えばsize()またはisEmpty()の実装をより困難にするのは、これらの方法は、一度に多くのロックを得ることが要求され、また、不正確な結果を返すリスクがあるからである.